⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 classwmi.c

📁 This is the library for all storage drivers. It simplifies writing a storage driver by implementing
💻 C
📖 第 1 页 / 共 2 页
字号:
/*++

Copyright (C) Microsoft Corporation, 1991 - 1999

Module Name:

    classwmi.c

Abstract:

    SCSI class driver routines

Environment:

    kernel mode only

Notes:


Revision History:

--*/

#include "stddef.h"
#include "ntddk.h"
#include "scsi.h"

#include "classpnp.h"

#include "mountdev.h"

#include <stdarg.h>

#include "wmistr.h"

NTSTATUS
ClassSystemControl(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    );

BOOLEAN
ClassFindGuid(
    PGUIDREGINFO GuidList,
    ULONG GuidCount,
    LPGUID Guid,
    PULONG GuidIndex
    );

//
// This is the name for the MOF resource that must be part of all drivers that
// register via this interface.
#define MOFRESOURCENAME L"MofResourceName"

//
// What can be paged ???
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, ClassSystemControl)
#pragma alloc_text(PAGE, ClassFindGuid)
#endif


/*++////////////////////////////////////////////////////////////////////////////

ClassFindGuid()

Routine Description:

    This routine will search the list of guids registered and return
    the index for the one that was registered.

Arguments:

    GuidList is the list of guids to search

    GuidCount is the count of guids in the list

    Guid is the guid being searched for

    *GuidIndex returns the index to the guid

Return Value:

    TRUE if guid is found else FALSE

--*/
BOOLEAN
ClassFindGuid(
    PGUIDREGINFO GuidList,
    ULONG GuidCount,
    LPGUID Guid,
    PULONG GuidIndex
    )
{
    ULONG i;

    PAGED_CODE();

    for (i = 0; i < GuidCount; i++)
    {
        if (IsEqualGUID(Guid, &GuidList[i].Guid))
        {
            *GuidIndex = i;
            return(TRUE);
        }
    }

    return(FALSE);
} // end ClassFindGuid()

/*++////////////////////////////////////////////////////////////////////////////

ClassSystemControl()

Routine Description:

    Dispatch routine for IRP_MJ_SYSTEM_CONTROL. This routine will process
    all wmi requests received, forwarding them if they are not for this
    driver or determining if the guid is valid and if so passing it to
    the driver specific function for handing wmi requests.

Arguments:

    DeviceObject - Supplies a pointer to the device object for this request.

    Irp - Supplies the Irp making the request.

Return Value:

    status

--*/
NTSTATUS
ClassSystemControl(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
{
    PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
    PCLASS_DRIVER_EXTENSION driverExtension;
    PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
    ULONG isRemoved;
    ULONG bufferSize;
    PUCHAR buffer;
    NTSTATUS status;
    UCHAR minorFunction;
    ULONG guidIndex;
    PCLASS_WMI_INFO classWmiInfo;

    PAGED_CODE();

    //
    // Make sure device has not been removed
    isRemoved = ClassAcquireRemoveLock(DeviceObject, Irp);
    if(isRemoved)
    {
        Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
        ClassReleaseRemoveLock(DeviceObject, Irp);
        ClassCompleteRequest(DeviceObject, Irp, IO_NO_INCREMENT);
        return STATUS_DEVICE_DOES_NOT_EXIST;
    }

    //
    // If the irp is not a WMI irp or it is not targetted at this device
    // or this device has not regstered with WMI then just forward it on.
    minorFunction = irpStack->MinorFunction;
    if ((minorFunction > IRP_MN_EXECUTE_METHOD) ||
        (irpStack->Parameters.WMI.ProviderId != (ULONG_PTR)DeviceObject) ||
        ((minorFunction != IRP_MN_REGINFO) &&
         (commonExtension->GuidRegInfo == NULL)))
    {
        //
        // CONSIDER: Do I need to hang onto lock until IoCallDriver returns ?
        IoSkipCurrentIrpStackLocation(Irp);
        ClassReleaseRemoveLock(DeviceObject, Irp);
        return(IoCallDriver(commonExtension->LowerDeviceObject, Irp));
    }

    buffer = (PUCHAR)irpStack->Parameters.WMI.Buffer;
    bufferSize = irpStack->Parameters.WMI.BufferSize;

    if (minorFunction != IRP_MN_REGINFO)
    {
        //
        // For all requests other than query registration info we are passed
        // a guid. Determine if the guid is one that is supported by the
        // device.
        if (ClassFindGuid(commonExtension->GuidRegInfo,
                            commonExtension->GuidCount,
                            (LPGUID)irpStack->Parameters.WMI.DataPath,
                            &guidIndex))
        {
            status = STATUS_SUCCESS;
        } else {
            status = STATUS_WMI_GUID_NOT_FOUND;
        }

        if (NT_SUCCESS(status) &&
            ((minorFunction == IRP_MN_QUERY_SINGLE_INSTANCE) ||
             (minorFunction == IRP_MN_CHANGE_SINGLE_INSTANCE) ||
             (minorFunction == IRP_MN_CHANGE_SINGLE_ITEM) ||
             (minorFunction == IRP_MN_EXECUTE_METHOD)))
        {
            if ( (((PWNODE_HEADER)buffer)->Flags) &
                                          WNODE_FLAG_STATIC_INSTANCE_NAMES)
            {
                if ( ((PWNODE_SINGLE_INSTANCE)buffer)->InstanceIndex != 0 )
                {
                    status = STATUS_WMI_INSTANCE_NOT_FOUND;
                }
            } else {
                status = STATUS_WMI_INSTANCE_NOT_FOUND;
            }
        }

        if (! NT_SUCCESS(status))
        {
            Irp->IoStatus.Status = status;
            ClassReleaseRemoveLock(DeviceObject, Irp);
            ClassCompleteRequest(DeviceObject, Irp, IO_NO_INCREMENT);
            return(status);
        }
    }

    driverExtension = commonExtension->DriverExtension;

    classWmiInfo = commonExtension->IsFdo ?
                           &driverExtension->InitData.FdoData.ClassWmiInfo :
                           &driverExtension->InitData.PdoData.ClassWmiInfo;
    switch(minorFunction)
    {
        case IRP_MN_REGINFO:
        {
            ULONG guidCount;
            PGUIDREGINFO guidList;
            PWMIREGINFOW wmiRegInfo;
            PWMIREGGUIDW wmiRegGuid;
            PDEVICE_OBJECT pdo;
            PUNICODE_STRING regPath;
            PWCHAR stringPtr;
            ULONG retSize;
            ULONG registryPathOffset;
            ULONG mofResourceOffset;
            ULONG bufferNeeded;
            ULONG i;
            ULONG_PTR nameInfo;
            ULONG nameSize, nameOffset, nameFlags;
            UNICODE_STRING name, mofName;
            PCLASS_QUERY_WMI_REGINFO_EX ClassQueryWmiRegInfoEx;

            name.Buffer = NULL;
            name.Length = 0;
            name.MaximumLength = 0;
            nameFlags = 0;

            ClassQueryWmiRegInfoEx = commonExtension->IsFdo ?
                               driverExtension->ClassFdoQueryWmiRegInfoEx :
                               driverExtension->ClassPdoQueryWmiRegInfoEx;
        
            if (ClassQueryWmiRegInfoEx == NULL)
            {
                status = classWmiInfo->ClassQueryWmiRegInfo(
                                                        DeviceObject,
                                                        &nameFlags,
                                                        &name);
                
                RtlInitUnicodeString(&mofName, MOFRESOURCENAME);
            } else {
                RtlInitUnicodeString(&mofName, L"");
                status = (*ClassQueryWmiRegInfoEx)(
                                                    DeviceObject,
                                                    &nameFlags,
                                                    &name,
                                                    &mofName);
            }

            if (NT_SUCCESS(status) &&
                (! (nameFlags &  WMIREG_FLAG_INSTANCE_PDO) &&
                (name.Buffer == NULL)))
            {
                //
                // if PDO flag not specified then an instance name must be
                status = STATUS_INVALID_DEVICE_REQUEST;
            }

            if (NT_SUCCESS(status))
            {
                guidList = classWmiInfo->GuidRegInfo;
                guidCount = classWmiInfo->GuidCount;

                nameOffset = sizeof(WMIREGINFO) +
                                      guidCount * sizeof(WMIREGGUIDW);

                if (nameFlags & WMIREG_FLAG_INSTANCE_PDO)
                {
                    nameSize = 0;
                    nameInfo = commonExtension->IsFdo ?
                                   (ULONG_PTR)((PFUNCTIONAL_DEVICE_EXTENSION)commonExtension)->LowerPdo :
                                   (ULONG_PTR)DeviceObject;
                } else {
                    nameFlags |= WMIREG_FLAG_INSTANCE_LIST;
                    nameSize = name.Length + sizeof(USHORT);
                    nameInfo = nameOffset;
                }

                mofResourceOffset = nameOffset + nameSize;

                registryPathOffset = mofResourceOffset +
                                  mofName.Length + sizeof(USHORT);

                regPath = &driverExtension->RegistryPath;
                bufferNeeded = registryPathOffset +
                regPath->Length + sizeof(USHORT);

                if (bufferNeeded <= bufferSize)
                {
                    retSize = bufferNeeded;

                    commonExtension->GuidCount = guidCount;
                    commonExtension->GuidRegInfo = guidList;

                    wmiRegInfo = (PWMIREGINFO)buffer;
                    wmiRegInfo->BufferSize = bufferNeeded;
                    wmiRegInfo->NextWmiRegInfo = 0;
                    wmiRegInfo->MofResourceName = mofResourceOffset;
                    wmiRegInfo->RegistryPath = registryPathOffset;
                    wmiRegInfo->GuidCount = guidCount;

                    for (i = 0; i < guidCount; i++)
                    {
                        wmiRegGuid = &wmiRegInfo->WmiRegGuid[i];
                        wmiRegGuid->Guid = guidList[i].Guid;
                        wmiRegGuid->Flags = guidList[i].Flags | nameFlags;
                        wmiRegGuid->InstanceInfo = nameInfo;
                        wmiRegGuid->InstanceCount = 1;
                    }

                    if ( nameFlags &  WMIREG_FLAG_INSTANCE_LIST)
                    {
                        if (bufferSize >= nameOffset+sizeof(WCHAR)+name.Length){
                            stringPtr = (PWCHAR)((PUCHAR)buffer + nameOffset);
                            *stringPtr++ = name.Length;
                            RtlCopyMemory(stringPtr, name.Buffer, name.Length);
                        }
                        else {
                            ASSERT(bufferSize >= nameOffset+sizeof(WCHAR)+name.Length);
                            status = STATUS_INVALID_BUFFER_SIZE;
                        }
                    }

                    if (bufferSize >= mofResourceOffset+sizeof(WCHAR)+mofName.Length){
                        stringPtr = (PWCHAR)((PUCHAR)buffer + mofResourceOffset);
                        *stringPtr++ = mofName.Length;
                        RtlCopyMemory(stringPtr, mofName.Buffer, mofName.Length);
                    }
                    else {
                        ASSERT(bufferSize >= mofResourceOffset+sizeof(WCHAR)+mofName.Length);
                        status = STATUS_INVALID_BUFFER_SIZE;
                    }
                    
                    if (bufferSize >= registryPathOffset+sizeof(WCHAR)+regPath->Length){
                        stringPtr = (PWCHAR)((PUCHAR)buffer + registryPathOffset);
                        *stringPtr++ = regPath->Length;
                        RtlCopyMemory(stringPtr,
                                  regPath->Buffer,
                                  regPath->Length);
                    }                     
                    else {
                        ASSERT(bufferSize >= registryPathOffset+sizeof(WCHAR)+regPath->Length);
                        status = STATUS_INVALID_BUFFER_SIZE;
                    }
                    
                } else {
                    *((PULONG)buffer) = bufferNeeded;
                    retSize = sizeof(ULONG);
                }
            } else {
                retSize = 0;
            }

            if (name.Buffer != NULL)
            {
                ExFreePool(name.Buffer);
            }

            Irp->IoStatus.Status = status;
            Irp->IoStatus.Information = retSize;
            ClassReleaseRemoveLock(DeviceObject, Irp);
            ClassCompleteRequest(DeviceObject, Irp, IO_NO_INCREMENT);
            return(status);
        }

        case IRP_MN_QUERY_ALL_DATA:
        {
            PWNODE_ALL_DATA wnode;
            ULONG bufferAvail;

            wnode = (PWNODE_ALL_DATA)buffer;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -