1 /*++
2
3 Copyright (C) Microsoft Corporation, 1991 - 1999
4
5 Module Name:
6
7 classwmi.c
8
9 Abstract:
10
11 SCSI class driver routines
12
13 Environment:
14
15 kernel mode only
16
17 Notes:
18
19
20 Revision History:
21
22 --*/
23
24 #ifndef __REACTOS__
25 #include "stddef.h"
26 #include "ntddk.h"
27 #include "scsi.h"
28
29 #include "classpnp.h"
30
31 #include "mountdev.h"
32
33 #include <stdarg.h>
34 #endif
35
36 #include "classp.h"
37 #include <wmistr.h>
38 #include <wmidata.h>
39 // #include <classlog.h> __REACTOS__
40
41 #ifdef DEBUG_USE_WPP
42 #include "classwmi.tmh"
43 #endif
44
45 #define TIME_STRING_LENGTH 25
46
47 BOOLEAN
48 ClassFindGuid(
49 PGUIDREGINFO GuidList,
50 ULONG GuidCount,
51 LPGUID Guid,
52 PULONG GuidIndex
53 );
54
55 NTSTATUS
56 ClassQueryInternalDataBlock(
57 IN PDEVICE_OBJECT DeviceObject,
58 IN PIRP Irp,
59 IN ULONG GuidIndex,
60 IN ULONG BufferAvail,
61 OUT PUCHAR Buffer
62 );
63
64 PWCHAR
65 ConvertTickToDateTime(
66 IN LARGE_INTEGER Tick,
67 _Out_writes_(TIME_STRING_LENGTH) PWCHAR String
68 );
69
70 BOOLEAN
71 ClassFindInternalGuid(
72 LPGUID Guid,
73 PULONG GuidIndex
74 );
75
76
77 //
78 // This is the name for the MOF resource that must be part of all drivers that
79 // register via this interface.
80 #define MOFRESOURCENAME L"MofResourceName"
81
82 //
83 // What can be paged ???
84 #ifdef ALLOC_PRAGMA
85 #pragma alloc_text(PAGE, ClassSystemControl)
86 #pragma alloc_text(PAGE, ClassFindGuid)
87 #pragma alloc_text(PAGE, ClassFindInternalGuid)
88 #endif
89
90 #ifdef __REACTOS__
91 #define MSStorageDriver_ClassErrorLogGuid {0xD5A9A51E, 0x03F9, 0x404d, {0x97, 0x22, 0x15, 0xF9, 0x0E, 0xB0, 0x70, 0x38}}
92 #endif
93
94 //
95 // Define WMI interface to all class drivers
96 //
97 GUIDREGINFO wmiClassGuids[] =
98 {
99 {
100 MSStorageDriver_ClassErrorLogGuid, 1, 0
101 }
102 };
103
104 #define MSStorageDriver_ClassErrorLogGuid_Index 0
105 #define NUM_CLASS_WMI_GUIDS (sizeof(wmiClassGuids) / sizeof(GUIDREGINFO))
106
107
108 /*++////////////////////////////////////////////////////////////////////////////
109
110 ClassFindGuid()
111
112 Routine Description:
113
114 This routine will search the list of guids registered and return
115 the index for the one that was registered.
116
117 Arguments:
118
119 GuidList is the list of guids to search
120
121 GuidCount is the count of guids in the list
122
123 Guid is the guid being searched for
124
125 *GuidIndex returns the index to the guid
126
127 Return Value:
128
129 TRUE if guid is found else FALSE
130
131 --*/
132 BOOLEAN
ClassFindGuid(PGUIDREGINFO GuidList,ULONG GuidCount,LPGUID Guid,PULONG GuidIndex)133 ClassFindGuid(
134 PGUIDREGINFO GuidList,
135 ULONG GuidCount,
136 LPGUID Guid,
137 PULONG GuidIndex
138 )
139 {
140 ULONG i;
141
142 PAGED_CODE();
143
144 for (i = 0; i < GuidCount; i++)
145 {
146 if (IsEqualGUID(Guid, &GuidList[i].Guid))
147 {
148 *GuidIndex = i;
149 return(TRUE);
150 }
151 }
152 return(FALSE);
153 } // end ClassFindGuid()
154
155 /*++////////////////////////////////////////////////////////////////////////////
156
157 ClassFindInternalGuid()
158
159 Routine Description:
160
161 This routine will search the list of internal guids registered and return
162 the index for the one that was registered.
163
164 Arguments:
165
166 Guid is the guid being searched for
167
168 *GuidIndex returns the index to the guid
169
170 Return Value:
171
172 TRUE if guid is found else FALSE
173
174 --*/
175 BOOLEAN
ClassFindInternalGuid(LPGUID Guid,PULONG GuidIndex)176 ClassFindInternalGuid(
177 LPGUID Guid,
178 PULONG GuidIndex
179 )
180 {
181 ULONG i;
182
183 PAGED_CODE();
184
185 for (i = 0; i < NUM_CLASS_WMI_GUIDS; i++)
186 {
187 if (IsEqualGUID(Guid, &wmiClassGuids[i].Guid))
188 {
189 *GuidIndex = i;
190 return(TRUE);
191 }
192 }
193
194 return(FALSE);
195 } // end ClassFindGuid()
196
197 /*++////////////////////////////////////////////////////////////////////////////
198
199 ClassSystemControl()
200
201 Routine Description:
202
203 Dispatch routine for IRP_MJ_SYSTEM_CONTROL. This routine will process
204 all wmi requests received, forwarding them if they are not for this
205 driver or determining if the guid is valid and if so passing it to
206 the driver specific function for handing wmi requests.
207
208 Arguments:
209
210 DeviceObject - Supplies a pointer to the device object for this request.
211
212 Irp - Supplies the Irp making the request.
213
214 Return Value:
215
216 status
217
218 --*/
219 NTSTATUS
220 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
ClassSystemControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)221 ClassSystemControl(
222 IN PDEVICE_OBJECT DeviceObject,
223 IN PIRP Irp
224 )
225 {
226 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
227 PCLASS_DRIVER_EXTENSION driverExtension;
228 PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
229 ULONG isRemoved;
230 ULONG bufferSize;
231 PUCHAR buffer;
232 NTSTATUS status;
233 UCHAR minorFunction;
234 ULONG guidIndex = (ULONG)-1;
235 PCLASS_WMI_INFO classWmiInfo;
236 BOOLEAN isInternalGuid = FALSE;
237
238 PAGED_CODE();
239
240 //
241 // Make sure device has not been removed
242 isRemoved = ClassAcquireRemoveLock(DeviceObject, Irp);
243 if(isRemoved)
244 {
245 Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
246 ClassReleaseRemoveLock(DeviceObject, Irp);
247 ClassCompleteRequest(DeviceObject, Irp, IO_NO_INCREMENT);
248 return STATUS_DEVICE_DOES_NOT_EXIST;
249 }
250
251 //
252 // If the irp is not a WMI irp or it is not targetted at this device
253 // or this device has not regstered with WMI then just forward it on.
254 minorFunction = irpStack->MinorFunction;
255 if ((minorFunction > IRP_MN_EXECUTE_METHOD) ||
256 (irpStack->Parameters.WMI.ProviderId != (ULONG_PTR)DeviceObject) ||
257 ((minorFunction != IRP_MN_REGINFO) &&
258 (commonExtension->GuidCount == 0)))
259 {
260 //
261 // CONSIDER: Do I need to hang onto lock until IoCallDriver returns ?
262 IoSkipCurrentIrpStackLocation(Irp);
263 ClassReleaseRemoveLock(DeviceObject, Irp);
264 return(IoCallDriver(commonExtension->LowerDeviceObject, Irp));
265 }
266
267 buffer = (PUCHAR)irpStack->Parameters.WMI.Buffer;
268 bufferSize = irpStack->Parameters.WMI.BufferSize;
269
270 if (minorFunction != IRP_MN_REGINFO)
271 {
272 //
273 // For all requests other than query registration info we are passed
274 // a guid. Determine if the guid is one that is supported by the
275 // device.
276 if (commonExtension->GuidRegInfo != NULL &&
277 ClassFindGuid(commonExtension->GuidRegInfo,
278 commonExtension->GuidCount,
279 (LPGUID)irpStack->Parameters.WMI.DataPath,
280 &guidIndex))
281 {
282 isInternalGuid = FALSE;
283 status = STATUS_SUCCESS;
284 } else if (ClassFindInternalGuid((LPGUID)irpStack->Parameters.WMI.DataPath,
285 &guidIndex)) {
286 isInternalGuid = TRUE;
287 status = STATUS_SUCCESS;
288 } else {
289 status = STATUS_WMI_GUID_NOT_FOUND;
290 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_WMI, "WMI GUID not found!"));
291 }
292
293 TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_WMI, "WMI Find Guid = %x, isInternalGuid = %x", status, isInternalGuid));
294 if (NT_SUCCESS(status) &&
295 ((minorFunction == IRP_MN_QUERY_SINGLE_INSTANCE) ||
296 (minorFunction == IRP_MN_CHANGE_SINGLE_INSTANCE) ||
297 (minorFunction == IRP_MN_CHANGE_SINGLE_ITEM) ||
298 (minorFunction == IRP_MN_EXECUTE_METHOD)))
299 {
300 if ( (((PWNODE_HEADER)buffer)->Flags) &
301 WNODE_FLAG_STATIC_INSTANCE_NAMES)
302 {
303 if ( ((PWNODE_SINGLE_INSTANCE)buffer)->InstanceIndex != 0 )
304 {
305 status = STATUS_WMI_INSTANCE_NOT_FOUND;
306 }
307 } else {
308 status = STATUS_WMI_INSTANCE_NOT_FOUND;
309 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_WMI, "WMI Instance not found!"));
310 }
311 }
312
313 if (! NT_SUCCESS(status))
314 {
315 Irp->IoStatus.Status = status;
316 ClassReleaseRemoveLock(DeviceObject, Irp);
317 ClassCompleteRequest(DeviceObject, Irp, IO_NO_INCREMENT);
318 return(status);
319 }
320 }
321
322 driverExtension = commonExtension->DriverExtension;
323
324 classWmiInfo = commonExtension->IsFdo ?
325 &driverExtension->InitData.FdoData.ClassWmiInfo :
326 &driverExtension->InitData.PdoData.ClassWmiInfo;
327 switch(minorFunction)
328 {
329 case IRP_MN_REGINFO:
330 {
331 ULONG guidCount;
332 PGUIDREGINFO guidList;
333 PWMIREGINFOW wmiRegInfo;
334 PWMIREGGUIDW wmiRegGuid;
335 PUNICODE_STRING regPath;
336 PWCHAR stringPtr;
337 ULONG retSize;
338 ULONG registryPathOffset;
339 ULONG mofResourceOffset;
340 ULONG bufferNeeded;
341 ULONG i;
342 ULONG_PTR nameInfo;
343 ULONG nameSize, nameOffset, nameFlags;
344 UNICODE_STRING name, mofName;
345 PCLASS_QUERY_WMI_REGINFO_EX ClassQueryWmiRegInfoEx;
346
347 name.Buffer = NULL;
348 name.Length = 0;
349 name.MaximumLength = 0;
350 nameFlags = 0;
351
352 ClassQueryWmiRegInfoEx = commonExtension->IsFdo ?
353 driverExtension->ClassFdoQueryWmiRegInfoEx :
354 driverExtension->ClassPdoQueryWmiRegInfoEx;
355
356 if ((classWmiInfo->GuidRegInfo != NULL) &&
357 (classWmiInfo->ClassQueryWmiRegInfo != NULL) &&
358 (ClassQueryWmiRegInfoEx == NULL))
359 {
360 status = classWmiInfo->ClassQueryWmiRegInfo(
361 DeviceObject,
362 &nameFlags,
363 &name);
364
365 RtlInitUnicodeString(&mofName, MOFRESOURCENAME);
366
367 } else if ((classWmiInfo->GuidRegInfo != NULL) && (ClassQueryWmiRegInfoEx != NULL)) {
368 RtlInitUnicodeString(&mofName, L"");
369
370 status = (*ClassQueryWmiRegInfoEx)(
371 DeviceObject,
372 &nameFlags,
373 &name,
374 &mofName);
375 } else {
376 RtlInitUnicodeString(&mofName, L"");
377 nameFlags = WMIREG_FLAG_INSTANCE_PDO;
378 status = STATUS_SUCCESS;
379 }
380
381 if (NT_SUCCESS(status) &&
382 (! (nameFlags & WMIREG_FLAG_INSTANCE_PDO) &&
383 (name.Buffer == NULL)))
384 {
385 //
386 // if PDO flag not specified then an instance name must be
387 status = STATUS_INVALID_DEVICE_REQUEST;
388 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_WMI, "Invalid Device Request!"));
389 }
390
391 if (NT_SUCCESS(status))
392 {
393 guidList = classWmiInfo->GuidRegInfo;
394 guidCount = (classWmiInfo->GuidRegInfo == NULL ? 0 : classWmiInfo->GuidCount) + NUM_CLASS_WMI_GUIDS;
395
396 nameOffset = sizeof(WMIREGINFO) +
397 guidCount * sizeof(WMIREGGUIDW);
398
399 if (nameFlags & WMIREG_FLAG_INSTANCE_PDO)
400 {
401 nameSize = 0;
402 nameInfo = commonExtension->IsFdo ?
403 (ULONG_PTR)((PFUNCTIONAL_DEVICE_EXTENSION)commonExtension)->LowerPdo :
404 (ULONG_PTR)DeviceObject;
405 } else {
406 nameFlags |= WMIREG_FLAG_INSTANCE_LIST;
407 nameSize = name.Length + sizeof(USHORT);
408 nameInfo = nameOffset;
409 }
410
411 mofResourceOffset = nameOffset + nameSize;
412
413 registryPathOffset = mofResourceOffset +
414 mofName.Length + sizeof(USHORT);
415
416 regPath = &driverExtension->RegistryPath;
417
418 bufferNeeded = registryPathOffset + regPath->Length;
419 bufferNeeded += sizeof(USHORT);
420
421 if (bufferNeeded <= bufferSize)
422 {
423 retSize = bufferNeeded;
424
425 commonExtension->GuidCount = guidCount;
426 commonExtension->GuidRegInfo = guidList;
427
428 wmiRegInfo = (PWMIREGINFO)buffer;
429 wmiRegInfo->BufferSize = bufferNeeded;
430 wmiRegInfo->NextWmiRegInfo = 0;
431 wmiRegInfo->MofResourceName = mofResourceOffset;
432 wmiRegInfo->RegistryPath = registryPathOffset;
433 wmiRegInfo->GuidCount = guidCount;
434
435 for (i = 0; i < classWmiInfo->GuidCount; i++)
436 {
437 wmiRegGuid = &wmiRegInfo->WmiRegGuid[i];
438 wmiRegGuid->Guid = guidList[i].Guid;
439 wmiRegGuid->Flags = guidList[i].Flags | nameFlags;
440 wmiRegGuid->InstanceInfo = nameInfo;
441 wmiRegGuid->InstanceCount = 1;
442 }
443 for (i = 0; i < NUM_CLASS_WMI_GUIDS; i++)
444 {
445 wmiRegGuid = &wmiRegInfo->WmiRegGuid[i + classWmiInfo->GuidCount];
446 wmiRegGuid->Guid = wmiClassGuids[i].Guid;
447 wmiRegGuid->Flags = wmiClassGuids[i].Flags | nameFlags;
448 wmiRegGuid->InstanceInfo = nameInfo;
449 wmiRegGuid->InstanceCount = 1;
450 }
451
452 if ( nameFlags & WMIREG_FLAG_INSTANCE_LIST)
453 {
454 bufferNeeded = nameOffset + sizeof(WCHAR);
455 bufferNeeded += name.Length;
456
457 if (bufferSize >= bufferNeeded){
458 stringPtr = (PWCHAR)((PUCHAR)buffer + nameOffset);
459 *stringPtr++ = name.Length;
460 RtlCopyMemory(stringPtr, name.Buffer, name.Length);
461 }
462 else {
463 NT_ASSERT(bufferSize >= bufferNeeded);
464 status = STATUS_INVALID_BUFFER_SIZE;
465 }
466 }
467
468 bufferNeeded = mofResourceOffset + sizeof(WCHAR);
469 bufferNeeded += mofName.Length;
470
471 if (bufferSize >= bufferNeeded){
472 stringPtr = (PWCHAR)((PUCHAR)buffer + mofResourceOffset);
473 *stringPtr++ = mofName.Length;
474 RtlCopyMemory(stringPtr, mofName.Buffer, mofName.Length);
475 }
476 else {
477 NT_ASSERT(bufferSize >= bufferNeeded);
478 status = STATUS_INVALID_BUFFER_SIZE;
479 }
480
481 bufferNeeded = registryPathOffset + sizeof(WCHAR);
482 bufferNeeded += regPath->Length;
483
484 if (bufferSize >= bufferNeeded){
485 stringPtr = (PWCHAR)((PUCHAR)buffer + registryPathOffset);
486 *stringPtr++ = regPath->Length;
487 RtlCopyMemory(stringPtr,
488 regPath->Buffer,
489 regPath->Length);
490 }
491 else {
492
493 NT_ASSERT(bufferSize >= bufferNeeded);
494 TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_WMI, "Invalid Buffer Size!"));
495 status = STATUS_INVALID_BUFFER_SIZE;
496 }
497
498 } else {
499 *((PULONG)buffer) = bufferNeeded;
500 retSize = sizeof(ULONG);
501 }
502 } else {
503 retSize = 0;
504 }
505
506 FREE_POOL(name.Buffer);
507
508 Irp->IoStatus.Status = status;
509 Irp->IoStatus.Information = retSize;
510 ClassReleaseRemoveLock(DeviceObject, Irp);
511 ClassCompleteRequest(DeviceObject, Irp, IO_NO_INCREMENT);
512 return(status);
513 }
514
515 case IRP_MN_QUERY_ALL_DATA:
516 {
517 PWNODE_ALL_DATA wnode;
518 ULONG bufferAvail;
519
520 wnode = (PWNODE_ALL_DATA)buffer;
521
522 if (bufferSize < sizeof(WNODE_ALL_DATA))
523 {
524 bufferAvail = 0;
525 } else {
526 bufferAvail = bufferSize - sizeof(WNODE_ALL_DATA);
527 }
528
529 wnode->DataBlockOffset = sizeof(WNODE_ALL_DATA);
530
531 NT_ASSERT(guidIndex != (ULONG)-1);
532 _Analysis_assume_(isInternalGuid);
533 if (isInternalGuid)
534 {
535 status = ClassQueryInternalDataBlock(
536 DeviceObject,
537 Irp,
538 guidIndex,
539 bufferAvail,
540 buffer + sizeof(WNODE_ALL_DATA));
541 } else {
542 status = classWmiInfo->ClassQueryWmiDataBlock(
543 DeviceObject,
544 Irp,
545 guidIndex,
546 bufferAvail,
547 buffer + sizeof(WNODE_ALL_DATA));
548 }
549 break;
550 }
551
552 case IRP_MN_QUERY_SINGLE_INSTANCE:
553 {
554 PWNODE_SINGLE_INSTANCE wnode;
555 ULONG dataBlockOffset;
556
557 wnode = (PWNODE_SINGLE_INSTANCE)buffer;
558
559 dataBlockOffset = wnode->DataBlockOffset;
560
561 NT_ASSERT(guidIndex != (ULONG)-1);
562 _Analysis_assume_(isInternalGuid);
563 if (isInternalGuid)
564 {
565 status = ClassQueryInternalDataBlock(
566 DeviceObject,
567 Irp,
568 guidIndex,
569 bufferSize - dataBlockOffset,
570 (PUCHAR)wnode + dataBlockOffset);
571 } else {
572 status = classWmiInfo->ClassQueryWmiDataBlock(
573 DeviceObject,
574 Irp,
575 guidIndex,
576 bufferSize - dataBlockOffset,
577 (PUCHAR)wnode + dataBlockOffset);
578 }
579 break;
580 }
581
582 case IRP_MN_CHANGE_SINGLE_INSTANCE:
583 {
584 PWNODE_SINGLE_INSTANCE wnode;
585
586 wnode = (PWNODE_SINGLE_INSTANCE)buffer;
587 _Analysis_assume_(isInternalGuid);
588 if (isInternalGuid)
589 {
590 status = ClassWmiCompleteRequest(DeviceObject,
591 Irp,
592 STATUS_WMI_GUID_NOT_FOUND,
593 0,
594 IO_NO_INCREMENT);
595 } else {
596
597 NT_ASSERT(guidIndex != (ULONG)-1);
598
599 status = classWmiInfo->ClassSetWmiDataBlock(
600 DeviceObject,
601 Irp,
602 guidIndex,
603 wnode->SizeDataBlock,
604 (PUCHAR)wnode + wnode->DataBlockOffset);
605 }
606
607 break;
608 }
609
610 case IRP_MN_CHANGE_SINGLE_ITEM:
611 {
612 PWNODE_SINGLE_ITEM wnode;
613
614 wnode = (PWNODE_SINGLE_ITEM)buffer;
615
616 NT_ASSERT(guidIndex != (ULONG)-1);
617 _Analysis_assume_(isInternalGuid);
618 if (isInternalGuid)
619 {
620 status = ClassWmiCompleteRequest(DeviceObject,
621 Irp,
622 STATUS_WMI_GUID_NOT_FOUND,
623 0,
624 IO_NO_INCREMENT);
625 } else {
626
627 NT_ASSERT(guidIndex != (ULONG)-1);
628
629 status = classWmiInfo->ClassSetWmiDataItem(
630 DeviceObject,
631 Irp,
632 guidIndex,
633 wnode->ItemId,
634 wnode->SizeDataItem,
635 (PUCHAR)wnode + wnode->DataBlockOffset);
636
637 }
638
639 break;
640 }
641
642 case IRP_MN_EXECUTE_METHOD:
643 {
644 PWNODE_METHOD_ITEM wnode;
645
646 wnode = (PWNODE_METHOD_ITEM)buffer;
647 _Analysis_assume_(isInternalGuid);
648 if (isInternalGuid)
649 {
650 status = ClassWmiCompleteRequest(DeviceObject,
651 Irp,
652 STATUS_WMI_GUID_NOT_FOUND,
653 0,
654 IO_NO_INCREMENT);
655 } else {
656
657 NT_ASSERT(guidIndex != (ULONG)-1);
658
659 status = classWmiInfo->ClassExecuteWmiMethod(
660 DeviceObject,
661 Irp,
662 guidIndex,
663 wnode->MethodId,
664 wnode->SizeDataBlock,
665 bufferSize - wnode->DataBlockOffset,
666 buffer + wnode->DataBlockOffset);
667 }
668
669 break;
670 }
671
672 case IRP_MN_ENABLE_EVENTS:
673 {
674 _Analysis_assume_(isInternalGuid);
675 if (isInternalGuid)
676 {
677 status = ClassWmiCompleteRequest(DeviceObject,
678 Irp,
679 STATUS_WMI_GUID_NOT_FOUND,
680 0,
681 IO_NO_INCREMENT);
682 } else {
683
684 NT_ASSERT(guidIndex != (ULONG)-1);
685
686 status = classWmiInfo->ClassWmiFunctionControl(
687 DeviceObject,
688 Irp,
689 guidIndex,
690 EventGeneration,
691 TRUE);
692 }
693 break;
694 }
695
696 case IRP_MN_DISABLE_EVENTS:
697 {
698 _Analysis_assume_(isInternalGuid);
699 if (isInternalGuid)
700 {
701 status = ClassWmiCompleteRequest(DeviceObject,
702 Irp,
703 STATUS_WMI_GUID_NOT_FOUND,
704 0,
705 IO_NO_INCREMENT);
706 } else {
707
708 NT_ASSERT(guidIndex != (ULONG)-1);
709
710 status = classWmiInfo->ClassWmiFunctionControl(
711 DeviceObject,
712 Irp,
713 guidIndex,
714 EventGeneration,
715 FALSE);
716 }
717 break;
718 }
719
720 case IRP_MN_ENABLE_COLLECTION:
721 {
722 _Analysis_assume_(isInternalGuid);
723 if (isInternalGuid)
724 {
725 status = ClassWmiCompleteRequest(DeviceObject,
726 Irp,
727 STATUS_WMI_GUID_NOT_FOUND,
728 0,
729 IO_NO_INCREMENT);
730 } else {
731
732 NT_ASSERT(guidIndex != (ULONG)-1);
733
734 status = classWmiInfo->ClassWmiFunctionControl(
735 DeviceObject,
736 Irp,
737 guidIndex,
738 DataBlockCollection,
739 TRUE);
740 }
741 break;
742 }
743
744 case IRP_MN_DISABLE_COLLECTION:
745 {
746 _Analysis_assume_(isInternalGuid);
747 if (isInternalGuid)
748 {
749 status = ClassWmiCompleteRequest(DeviceObject,
750 Irp,
751 STATUS_WMI_GUID_NOT_FOUND,
752 0,
753 IO_NO_INCREMENT);
754 } else {
755
756 NT_ASSERT(guidIndex != (ULONG)-1);
757
758 status = classWmiInfo->ClassWmiFunctionControl(
759 DeviceObject,
760 Irp,
761 guidIndex,
762 DataBlockCollection,
763 FALSE);
764 }
765
766 break;
767 }
768
769 default:
770 {
771 status = STATUS_INVALID_DEVICE_REQUEST;
772 break;
773 }
774
775 }
776
777 return(status);
778 } // end ClassSystemControl()
779
780
781 NTSTATUS
ClassQueryInternalDataBlock(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN ULONG GuidIndex,IN ULONG BufferAvail,OUT PUCHAR Buffer)782 ClassQueryInternalDataBlock(
783 IN PDEVICE_OBJECT DeviceObject,
784 IN PIRP Irp,
785 IN ULONG GuidIndex,
786 IN ULONG BufferAvail,
787 OUT PUCHAR Buffer
788 )
789 /*++
790
791 Routine Description:
792
793 This routine allows querying for the contents of an internal WMI
794 data block. When the driver has finished filling the data block it
795 must call ClassWmiCompleteRequest to complete the irp.
796
797 Arguments:
798
799 DeviceObject is the device whose data block is being queried
800
801 Irp is the Irp that makes this request
802
803 GuidIndex is the index into the list of guids provided when the
804 device registered
805
806 BufferAvail on has the maximum size available to write the data
807 block.
808
809 Buffer on return is filled with the returned data block
810
811
812 Return Value:
813
814 status
815
816 --*/
817 {
818 NTSTATUS status;
819 #ifndef __REACTOS__ // WMI in not a thing on ReactOS yet
820 ULONG sizeNeeded = 0, i;
821 PFUNCTIONAL_DEVICE_EXTENSION fdoExt = DeviceObject->DeviceExtension;
822 if (GuidIndex == MSStorageDriver_ClassErrorLogGuid_Index) {
823
824 //
825 // NOTE - ClassErrorLog is still using SCSI_REQUEST_BLOCK and will not be
826 // updated to support extended SRB until classpnp is updated to send >16
827 // byte CDBs. Extended SRBs will be translated to SCSI_REQUEST_BLOCK.
828 //
829 sizeNeeded = MSStorageDriver_ClassErrorLog_SIZE;
830 if (BufferAvail >= sizeNeeded) {
831 PMSStorageDriver_ClassErrorLog errorLog = (PMSStorageDriver_ClassErrorLog) Buffer;
832 PMSStorageDriver_ClassErrorLogEntry logEntry;
833 PMSStorageDriver_ScsiRequestBlock srbBlock;
834 PMSStorageDriver_SenseData senseData;
835 PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
836 PCLASS_ERROR_LOG_DATA fdoLogEntry;
837 PSCSI_REQUEST_BLOCK fdoSRBBlock;
838 PSENSE_DATA fdoSenseData;
839 errorLog->numEntries = NUM_ERROR_LOG_ENTRIES;
840 for (i = 0; i < NUM_ERROR_LOG_ENTRIES; i++) {
841 fdoLogEntry = &fdoData->ErrorLogs[i];
842 fdoSRBBlock = &fdoLogEntry->Srb;
843 fdoSenseData = &fdoLogEntry->SenseData;
844 logEntry = &errorLog->logEntries[i];
845 srbBlock = &logEntry->srb;
846 senseData = &logEntry->senseData;
847 logEntry->tickCount = fdoLogEntry->TickCount.QuadPart;
848 logEntry->portNumber = fdoLogEntry->PortNumber;
849 logEntry->errorPaging = (fdoLogEntry->ErrorPaging == 0 ? FALSE : TRUE);
850 logEntry->errorRetried = (fdoLogEntry->ErrorRetried == 0 ? FALSE : TRUE);
851 logEntry->errorUnhandled = (fdoLogEntry->ErrorUnhandled == 0 ? FALSE : TRUE);
852 logEntry->errorReserved = fdoLogEntry->ErrorReserved;
853 RtlMoveMemory(logEntry->reserved, fdoLogEntry->Reserved, sizeof(logEntry->reserved));
854 ConvertTickToDateTime(fdoLogEntry->TickCount, logEntry->eventTime);
855
856 srbBlock->length = fdoSRBBlock->Length;
857 srbBlock->function = fdoSRBBlock->Function;
858 srbBlock->srbStatus = fdoSRBBlock->SrbStatus;
859 srbBlock->scsiStatus = fdoSRBBlock->ScsiStatus;
860 srbBlock->pathID = fdoSRBBlock->PathId;
861 srbBlock->targetID = fdoSRBBlock->TargetId;
862 srbBlock->lun = fdoSRBBlock->Lun;
863 srbBlock->queueTag = fdoSRBBlock->QueueTag;
864 srbBlock->queueAction = fdoSRBBlock->QueueAction;
865 srbBlock->cdbLength = fdoSRBBlock->CdbLength;
866 srbBlock->senseInfoBufferLength = fdoSRBBlock->SenseInfoBufferLength;
867 srbBlock->srbFlags = fdoSRBBlock->SrbFlags;
868 srbBlock->dataTransferLength = fdoSRBBlock->DataTransferLength;
869 srbBlock->timeOutValue = fdoSRBBlock->TimeOutValue;
870 srbBlock->dataBuffer = (ULONGLONG) fdoSRBBlock->DataBuffer;
871 srbBlock->senseInfoBuffer = (ULONGLONG) fdoSRBBlock->SenseInfoBuffer;
872 srbBlock->nextSRB = (ULONGLONG) fdoSRBBlock->NextSrb;
873 srbBlock->originalRequest = (ULONGLONG) fdoSRBBlock->OriginalRequest;
874 srbBlock->srbExtension = (ULONGLONG) fdoSRBBlock->SrbExtension;
875 srbBlock->internalStatus = fdoSRBBlock->InternalStatus;
876 #if defined(_WIN64)
877 srbBlock->reserved = fdoSRBBlock->Reserved;
878 #else
879 srbBlock->reserved = 0;
880 #endif
881 RtlMoveMemory(srbBlock->cdb, fdoSRBBlock->Cdb, sizeof(srbBlock->cdb));
882
883 //
884 // Note: Sense data has been converted into Fixed format before it was
885 // put in the log. Therefore, no conversion is needed here.
886 //
887 senseData->errorCode = fdoSenseData->ErrorCode;
888 senseData->valid = (fdoSenseData->Valid == 0 ? FALSE : TRUE);
889 senseData->segmentNumber = fdoSenseData->SegmentNumber;
890 senseData->senseKey = fdoSenseData->SenseKey;
891 senseData->reserved = (fdoSenseData->Reserved == 0 ? FALSE : TRUE);
892 senseData->incorrectLength = (fdoSenseData->IncorrectLength == 0 ? FALSE : TRUE);
893 senseData->endOfMedia = (fdoSenseData->EndOfMedia == 0 ? FALSE : TRUE);
894 senseData->fileMark = (fdoSenseData->FileMark == 0 ? FALSE : TRUE);
895 RtlMoveMemory(senseData->information, fdoSenseData->Information, sizeof(senseData->information));
896 senseData->additionalSenseLength = fdoSenseData->AdditionalSenseLength;
897 RtlMoveMemory(senseData->commandSpecificInformation, fdoSenseData->CommandSpecificInformation, sizeof(senseData->commandSpecificInformation));
898 senseData->additionalSenseCode = fdoSenseData->AdditionalSenseCode;
899 senseData->additionalSenseCodeQualifier = fdoSenseData->AdditionalSenseCodeQualifier;
900 senseData->fieldReplaceableUnitCode = fdoSenseData->FieldReplaceableUnitCode;
901 RtlMoveMemory(senseData->senseKeySpecific, fdoSenseData->SenseKeySpecific, sizeof(senseData->senseKeySpecific));
902 }
903 status = STATUS_SUCCESS;
904 } else {
905 status = STATUS_BUFFER_TOO_SMALL;
906 }
907 } else if (GuidIndex > 0 && GuidIndex < NUM_CLASS_WMI_GUIDS) {
908 status = STATUS_WMI_INSTANCE_NOT_FOUND;
909 } else {
910 status = STATUS_WMI_GUID_NOT_FOUND;
911 }
912 #else
913 ULONG sizeNeeded = 0;
914 status = STATUS_WMI_GUID_NOT_FOUND;
915 #endif
916 status = ClassWmiCompleteRequest(DeviceObject,
917 Irp,
918 status,
919 sizeNeeded,
920 IO_NO_INCREMENT);
921 return status;
922 }
923
924 PWCHAR
ConvertTickToDateTime(IN LARGE_INTEGER Tick,_Out_writes_ (TIME_STRING_LENGTH)PWCHAR String)925 ConvertTickToDateTime(
926 IN LARGE_INTEGER Tick,
927 _Out_writes_(TIME_STRING_LENGTH) PWCHAR String
928 )
929
930 /*++
931
932 Routine Description:
933
934 This routine converts a tick count to a datetime (MOF) data type
935
936 Arguments:
937
938 Tick - The tick count that needs to be converted
939 String - The buffer to hold the time string, must be able to hold WCHAR[25]
940
941 Return Value:
942
943 The time string
944
945 --*/
946
947 {
948 LARGE_INTEGER nowTick, nowTime, time;
949 ULONG maxInc = 0;
950 TIME_FIELDS timeFields = {0};
951 WCHAR outDateTime[TIME_STRING_LENGTH + 1];
952
953 nowTick.QuadPart = 0;
954 nowTime.QuadPart = 0;
955 //
956 // Translate the tick count to a system time
957 //
958 KeQueryTickCount(&nowTick);
959 maxInc = KeQueryTimeIncrement();
960 KeQuerySystemTime(&nowTime);
961 time.QuadPart = nowTime.QuadPart - ((nowTick.QuadPart - Tick.QuadPart) * maxInc);
962
963 RtlTimeToTimeFields(&time, &timeFields);
964
965 //
966 // The buffer String is of size MAX_PATH. Use that to specify the buffer size.
967 //
968 //yyyymmddhhmmss.mmmmmmsutc
969 RtlStringCbPrintfW(outDateTime, sizeof(outDateTime), L"%04d%02d%02d%02d%02d%02d.%03d***+000", timeFields.Year, timeFields.Month, timeFields.Day, timeFields.Hour, timeFields.Minute, timeFields.Second, timeFields.Milliseconds);
970 RtlMoveMemory(String, outDateTime, sizeof(WCHAR) * TIME_STRING_LENGTH);
971 return String;
972 }
973
974 /*++////////////////////////////////////////////////////////////////////////////
975
976 ClassWmiCompleteRequest()
977
978 Routine Description:
979
980
981 This routine will do the work of completing a WMI irp. Depending upon the
982 the WMI request this routine will fixup the returned WNODE appropriately.
983
984 NOTE: This routine assumes that the ClassRemoveLock is held and it will
985 release it.
986
987 Arguments:
988
989 DeviceObject - Supplies a pointer to the device object for this request.
990
991 Irp - Supplies the Irp making the request.
992
993 Status - Status to complete the irp with. STATUS_BUFFER_TOO_SMALL is used
994 to indicate that more buffer is required for the data requested.
995
996 BufferUsed - number of bytes of actual data to return (not including WMI
997 specific structures)
998
999 PriorityBoost - priority boost to pass to ClassCompleteRequest
1000
1001 Return Value:
1002
1003 status
1004
1005 --*/
1006 SCSIPORT_API
1007 NTSTATUS
1008 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
ClassWmiCompleteRequest(_In_ PDEVICE_OBJECT DeviceObject,_Inout_ PIRP Irp,_In_ NTSTATUS Status,_In_ ULONG BufferUsed,_In_ CCHAR PriorityBoost)1009 ClassWmiCompleteRequest(
1010 _In_ PDEVICE_OBJECT DeviceObject,
1011 _Inout_ PIRP Irp,
1012 _In_ NTSTATUS Status,
1013 _In_ ULONG BufferUsed,
1014 _In_ CCHAR PriorityBoost
1015 )
1016 {
1017 PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
1018 PUCHAR buffer;
1019 ULONG retSize;
1020 UCHAR minorFunction;
1021
1022 minorFunction = irpStack->MinorFunction;
1023 buffer = (PUCHAR)irpStack->Parameters.WMI.Buffer;
1024
1025 switch(minorFunction)
1026 {
1027 case IRP_MN_QUERY_ALL_DATA:
1028 {
1029 PWNODE_ALL_DATA wnode;
1030 PWNODE_TOO_SMALL wnodeTooSmall;
1031 ULONG bufferNeeded;
1032
1033 wnode = (PWNODE_ALL_DATA)buffer;
1034
1035 bufferNeeded = sizeof(WNODE_ALL_DATA) + BufferUsed;
1036
1037 if (NT_SUCCESS(Status))
1038 {
1039 retSize = bufferNeeded;
1040 wnode->WnodeHeader.BufferSize = bufferNeeded;
1041 KeQuerySystemTime(&wnode->WnodeHeader.TimeStamp);
1042 wnode->WnodeHeader.Flags |= WNODE_FLAG_FIXED_INSTANCE_SIZE;
1043 wnode->FixedInstanceSize = BufferUsed;
1044 wnode->InstanceCount = 1;
1045
1046 } else if (Status == STATUS_BUFFER_TOO_SMALL) {
1047 wnodeTooSmall = (PWNODE_TOO_SMALL)wnode;
1048
1049 wnodeTooSmall->WnodeHeader.BufferSize = sizeof(WNODE_TOO_SMALL);
1050 wnodeTooSmall->WnodeHeader.Flags = WNODE_FLAG_TOO_SMALL;
1051 wnodeTooSmall->SizeNeeded = sizeof(WNODE_ALL_DATA) + BufferUsed;
1052 retSize = sizeof(WNODE_TOO_SMALL);
1053 Status = STATUS_SUCCESS;
1054 } else {
1055 retSize = 0;
1056 }
1057 break;
1058 }
1059
1060 case IRP_MN_QUERY_SINGLE_INSTANCE:
1061 {
1062 PWNODE_SINGLE_INSTANCE wnode;
1063 PWNODE_TOO_SMALL wnodeTooSmall;
1064 ULONG bufferNeeded;
1065
1066 wnode = (PWNODE_SINGLE_INSTANCE)buffer;
1067
1068 bufferNeeded = wnode->DataBlockOffset + BufferUsed;
1069
1070 if (NT_SUCCESS(Status))
1071 {
1072 retSize = bufferNeeded;
1073 wnode->WnodeHeader.BufferSize = bufferNeeded;
1074 KeQuerySystemTime(&wnode->WnodeHeader.TimeStamp);
1075 wnode->SizeDataBlock = BufferUsed;
1076
1077 } else if (Status == STATUS_BUFFER_TOO_SMALL) {
1078 wnodeTooSmall = (PWNODE_TOO_SMALL)wnode;
1079
1080 wnodeTooSmall->WnodeHeader.BufferSize = sizeof(WNODE_TOO_SMALL);
1081 wnodeTooSmall->WnodeHeader.Flags = WNODE_FLAG_TOO_SMALL;
1082 wnodeTooSmall->SizeNeeded = bufferNeeded;
1083 retSize = sizeof(WNODE_TOO_SMALL);
1084 Status = STATUS_SUCCESS;
1085 } else {
1086 retSize = 0;
1087 }
1088 break;
1089 }
1090
1091 case IRP_MN_EXECUTE_METHOD:
1092 {
1093 PWNODE_METHOD_ITEM wnode;
1094 PWNODE_TOO_SMALL wnodeTooSmall;
1095 ULONG bufferNeeded;
1096
1097 wnode = (PWNODE_METHOD_ITEM)buffer;
1098
1099 bufferNeeded = wnode->DataBlockOffset + BufferUsed;
1100
1101 if (NT_SUCCESS(Status))
1102 {
1103 retSize = bufferNeeded;
1104 wnode->WnodeHeader.BufferSize = bufferNeeded;
1105 KeQuerySystemTime(&wnode->WnodeHeader.TimeStamp);
1106 wnode->SizeDataBlock = BufferUsed;
1107
1108 } else if (Status == STATUS_BUFFER_TOO_SMALL) {
1109 wnodeTooSmall = (PWNODE_TOO_SMALL)wnode;
1110
1111 wnodeTooSmall->WnodeHeader.BufferSize = sizeof(WNODE_TOO_SMALL);
1112 wnodeTooSmall->WnodeHeader.Flags = WNODE_FLAG_TOO_SMALL;
1113 wnodeTooSmall->SizeNeeded = bufferNeeded;
1114 retSize = sizeof(WNODE_TOO_SMALL);
1115 Status = STATUS_SUCCESS;
1116 } else {
1117 retSize = 0;
1118 }
1119 break;
1120 }
1121
1122 default:
1123 {
1124 //
1125 // All other requests don't return any data
1126 retSize = 0;
1127 break;
1128 }
1129
1130 }
1131
1132 Irp->IoStatus.Status = Status;
1133 Irp->IoStatus.Information = retSize;
1134 ClassReleaseRemoveLock(DeviceObject, Irp);
1135 ClassCompleteRequest(DeviceObject, Irp, PriorityBoost);
1136 return(Status);
1137 } // end ClassWmiCompleteRequest()
1138
1139 /*++////////////////////////////////////////////////////////////////////////////
1140
1141 ClassWmiFireEvent()
1142
1143 Routine Description:
1144
1145 This routine will fire a WMI event using the data buffer passed. This
1146 routine may be called at or below DPC level
1147
1148 Arguments:
1149
1150 DeviceObject - Supplies a pointer to the device object for this event
1151
1152 Guid is pointer to the GUID that represents the event
1153
1154 InstanceIndex is the index of the instance of the event
1155
1156 EventDataSize is the number of bytes of data that is being fired with
1157 with the event
1158
1159 EventData is the data that is fired with the events. This may be NULL
1160 if there is no data associated with the event
1161
1162
1163 Return Value:
1164
1165 status
1166
1167 --*/
_IRQL_requires_max_(DISPATCH_LEVEL)1168 _IRQL_requires_max_(DISPATCH_LEVEL)
1169 NTSTATUS
1170 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
1171 ClassWmiFireEvent(
1172 _In_ PDEVICE_OBJECT DeviceObject,
1173 _In_ LPGUID Guid,
1174 _In_ ULONG InstanceIndex,
1175 _In_ ULONG EventDataSize,
1176 _In_reads_bytes_(EventDataSize) PVOID EventData
1177 )
1178 {
1179
1180 ULONG sizeNeeded;
1181 PWNODE_SINGLE_INSTANCE event;
1182 NTSTATUS status;
1183
1184 if (EventData == NULL)
1185 {
1186 EventDataSize = 0;
1187 }
1188
1189 sizeNeeded = sizeof(WNODE_SINGLE_INSTANCE) + EventDataSize;
1190
1191 event = ExAllocatePoolWithTag(NonPagedPoolNx, sizeNeeded, CLASS_TAG_WMI);
1192 if (event != NULL)
1193 {
1194 RtlZeroMemory(event, sizeNeeded);
1195 event->WnodeHeader.Guid = *Guid;
1196 event->WnodeHeader.ProviderId = IoWMIDeviceObjectToProviderId(DeviceObject);
1197 event->WnodeHeader.BufferSize = sizeNeeded;
1198 event->WnodeHeader.Flags = WNODE_FLAG_SINGLE_INSTANCE |
1199 WNODE_FLAG_EVENT_ITEM |
1200 WNODE_FLAG_STATIC_INSTANCE_NAMES;
1201 KeQuerySystemTime(&event->WnodeHeader.TimeStamp);
1202
1203 event->InstanceIndex = InstanceIndex;
1204 event->SizeDataBlock = EventDataSize;
1205 event->DataBlockOffset = sizeof(WNODE_SINGLE_INSTANCE);
1206 if (EventData != NULL)
1207 {
1208 RtlCopyMemory( &event->VariableData, EventData, EventDataSize);
1209 }
1210
1211 status = IoWMIWriteEvent(event);
1212 if (! NT_SUCCESS(status))
1213 {
1214 FREE_POOL(event);
1215 }
1216 } else {
1217 status = STATUS_INSUFFICIENT_RESOURCES;
1218 }
1219
1220 return(status);
1221 } // end ClassWmiFireEvent()
1222