VOID
VIOSerialPortPnpNotifyWork(
    IN WDFWORKITEM  WorkItem
    )
{
    PRAWPDO_VIOSERIAL_PORT  pdoData = RawPdoSerialPortGetData(WorkItem);
    PVIOSERIAL_PORT         pport = pdoData->port;
    PTARGET_DEVICE_CUSTOM_NOTIFICATION  notification;
    ULONG                               requiredSize;
    NTSTATUS                            status;
    VIRTIO_PORT_STATUS_CHANGE           portStatus = {0};

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> %s\n", __FUNCTION__);
    portStatus.Version = 1;
    portStatus.Reason = pport->HostConnected;

    status = RtlULongAdd((sizeof(TARGET_DEVICE_CUSTOM_NOTIFICATION) - sizeof(UCHAR)),
                                 sizeof(VIRTIO_PORT_STATUS_CHANGE),
                                 &requiredSize);

    if (NT_SUCCESS(status))
    {
        notification = (PTARGET_DEVICE_CUSTOM_NOTIFICATION)
                       ExAllocatePoolWithTag(NonPagedPool,
                                 requiredSize,
                                 VIOSERIAL_DRIVER_MEMORY_TAG);

        if (notification != NULL)
        {
            RtlZeroMemory(notification, requiredSize);
            notification->Version = 1;
            notification->Size = (USHORT)(requiredSize);
            notification->FileObject = NULL;
            notification->NameBufferOffset = -1;
            notification->Event = GUID_VIOSERIAL_PORT_CHANGE_STATUS;
            RtlCopyMemory(notification->CustomDataBuffer, &portStatus, sizeof(VIRTIO_PORT_STATUS_CHANGE));
            if(WdfDeviceGetDevicePnpState(pport->Device) == WdfDevStatePnpStarted)
            {
               status = IoReportTargetDeviceChangeAsynchronous(
                                 WdfDeviceWdmGetPhysicalDevice(pport->Device),
                                 notification,
                                 NULL,
                                 NULL);
               if (!NT_SUCCESS(status))
               {
                    TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                                 "IoReportTargetDeviceChangeAsynchronous Failed! status = 0x%x\n", status);
               }
            }
            ExFreePoolWithTag(notification, VIOSERIAL_DRIVER_MEMORY_TAG);
        }
    }
    WdfObjectDelete(WorkItem);
    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- %s\n", __FUNCTION__);
}
Exemple #2
0
NTKERNELAPI
NTSTATUS
FsRtlNotifyVolumeEvent (
    IN PFILE_OBJECT FileObject,
    IN ULONG EventCode
    )

/*++

Routine Description:

    This routine notifies any registered applications that a 
    volume is being locked, unlocked, etc.  

Arguments:

    FileeObject - Supplies a file object for the volume being
        locked.

    EventCode - Which event is occuring -- e.g. FSRTL_VOLUME_LOCK
        
Return Value:

    Status of the notification.

--*/

{
    NTSTATUS Status = STATUS_SUCCESS;

    TARGET_DEVICE_CUSTOM_NOTIFICATION Event;
    PDEVICE_OBJECT Pdo;

    //
    //  Retrieve the device object associated with this file object.
    //

    Status = IoGetRelatedTargetDevice( FileObject, &Pdo );

    if (NT_SUCCESS( Status )) {

        ASSERT(Pdo != NULL);

        Event.Version = 1;
        Event.FileObject = NULL;
        Event.NameBufferOffset = -1;
        Event.Size = (USHORT)FIELD_OFFSET( TARGET_DEVICE_CUSTOM_NOTIFICATION, CustomDataBuffer );

        switch (EventCode) {

        case FSRTL_VOLUME_DISMOUNT:
            
            RtlCopyMemory( &Event.Event, &GUID_IO_VOLUME_DISMOUNT, sizeof( GUID ));
            break;
            
        case FSRTL_VOLUME_DISMOUNT_FAILED:
            
            RtlCopyMemory( &Event.Event, &GUID_IO_VOLUME_DISMOUNT_FAILED, sizeof( GUID ));
            break;            

        case FSRTL_VOLUME_LOCK:
        
            RtlCopyMemory( &Event.Event, &GUID_IO_VOLUME_LOCK, sizeof( GUID ));
            break;

        case FSRTL_VOLUME_LOCK_FAILED:
        
            RtlCopyMemory( &Event.Event, &GUID_IO_VOLUME_LOCK_FAILED, sizeof( GUID ));
            break;
        
        case FSRTL_VOLUME_MOUNT:
            
            //
            //  Mount notification is asynchronous to avoid deadlocks when someone 
            //  unwittingly causes a mount in the course of handling some other
            //  PnP notification, e.g. MountMgr's device arrival code.
            //
            
            RtlCopyMemory( &Event.Event, &GUID_IO_VOLUME_MOUNT, sizeof( GUID ));
            IoReportTargetDeviceChangeAsynchronous( Pdo, &Event, NULL, NULL );
            ObDereferenceObject( Pdo );
            return STATUS_SUCCESS;
            break;

        case FSRTL_VOLUME_UNLOCK:
        
            RtlCopyMemory( &Event.Event, &GUID_IO_VOLUME_UNLOCK, sizeof( GUID ));
            break;
            
        default:

            ObDereferenceObject( Pdo );
            return STATUS_INVALID_PARAMETER;
        }
        
        IoReportTargetDeviceChange( Pdo, &Event );
        ObDereferenceObject( Pdo );
    }

    return Status;
}
Exemple #3
0
/*
 * @implemented
 */
VOID
MountMgrNotifyNameChange(IN PDEVICE_EXTENSION DeviceExtension,
                         IN PUNICODE_STRING DeviceName,
                         IN BOOLEAN ValidateVolume)
{
    PIRP Irp;
    KEVENT Event;
    NTSTATUS Status;
    PLIST_ENTRY NextEntry;
    PFILE_OBJECT FileObject;
    PIO_STACK_LOCATION Stack;
    PDEVICE_OBJECT DeviceObject;
    IO_STATUS_BLOCK IoStatusBlock;
    PDEVICE_RELATIONS DeviceRelations;
    PDEVICE_INFORMATION DeviceInformation;
    TARGET_DEVICE_CUSTOM_NOTIFICATION DeviceNotification;

    /* If we have to validate volume */
    if (ValidateVolume)
    {
        /* Then, ensure we can find the device */
        NextEntry = DeviceExtension->DeviceListHead.Flink;
        while (NextEntry != &(DeviceExtension->DeviceListHead))
        {
            DeviceInformation = CONTAINING_RECORD(NextEntry, DEVICE_INFORMATION, DeviceListEntry);
            if (RtlCompareUnicodeString(DeviceName, &(DeviceInformation->DeviceName), TRUE) == 0)
            {
                break;
            }
        }

        /* No need to notify for a PnP device or if we didn't find the device */
        if (NextEntry == &(DeviceExtension->DeviceListHead) ||
            !DeviceInformation->ManuallyRegistered)
        {
            return;
        }
    }

    /* Then, get device object */
    Status = IoGetDeviceObjectPointer(DeviceName,
                                      FILE_READ_ATTRIBUTES,
                                      &FileObject,
                                      &DeviceObject);
    if (!NT_SUCCESS(Status))
    {
        return;
    }

    DeviceObject = IoGetAttachedDeviceReference(FileObject->DeviceObject);

    KeInitializeEvent(&Event, NotificationEvent, FALSE);

    /* Set up empty IRP (yes, yes!) */
    Irp = IoBuildDeviceIoControlRequest(0,
                                        DeviceObject,
                                        NULL,
                                        0,
                                        NULL,
                                        0,
                                        FALSE,
                                        &Event,
                                        &IoStatusBlock);
    if (!Irp)
    {
        ObDereferenceObject(DeviceObject);
        ObDereferenceObject(FileObject);
        return;
    }

    Stack = IoGetNextIrpStackLocation(Irp);

    Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
    Irp->IoStatus.Information = 0;

    /* Properly set it, we want to query device relations */
    Stack->MajorFunction = IRP_MJ_PNP;
    Stack->MinorFunction = IRP_MN_QUERY_DEVICE_RELATIONS;
    Stack->Parameters.QueryDeviceRelations.Type = TargetDeviceRelation;
    Stack->FileObject = FileObject;

    /* And call driver */
    Status = IoCallDriver(DeviceObject, Irp);
    if (Status == STATUS_PENDING)
    {
        KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
        Status = IoStatusBlock.Status;
    }

    ObDereferenceObject(DeviceObject);
    ObDereferenceObject(FileObject);

    if (!NT_SUCCESS(Status))
    {
        return;
    }

    /* Validate device return */
    DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information;
    if (DeviceRelations->Count < 1)
    {
        ExFreePool(DeviceRelations);
        return;
    }

    DeviceObject = DeviceRelations->Objects[0];
    ExFreePool(DeviceRelations);

    /* Set up real notification */
    DeviceNotification.Version = 1;
    DeviceNotification.Size = sizeof(TARGET_DEVICE_CUSTOM_NOTIFICATION);
    DeviceNotification.Event = GUID_IO_VOLUME_NAME_CHANGE;
    DeviceNotification.FileObject = NULL;
    DeviceNotification.NameBufferOffset = -1;

    /* And report */
    IoReportTargetDeviceChangeAsynchronous(DeviceObject,
                                           &DeviceNotification,
                                           NULL, NULL);

    ObDereferenceObject(DeviceObject);

    return;
}