Пример #1
0
NTSTATUS
BthEchoCliRetrieveServerBthAddress(
    __in PBTHECHOSAMPLE_CLIENT_CONTEXT DevCtx
    )
/*++

Description:

    Retrieve server Bth address

Arguments:

    DevCtx - Client context where we store bth address

Return Value:

    NTSTATUS Status code.

--*/
{
    NTSTATUS status, statusReuse;
    WDF_MEMORY_DESCRIPTOR outMemDesc;
    WDF_REQUEST_REUSE_PARAMS ReuseParams;
    BTH_DEVICE_INFO serverDeviceInfo;
    
    WDF_REQUEST_REUSE_PARAMS_INIT(&ReuseParams, WDF_REQUEST_REUSE_NO_FLAGS, STATUS_NOT_SUPPORTED);
    statusReuse = WdfRequestReuse(DevCtx->Header.Request, &ReuseParams);    
    ASSERT(NT_SUCCESS(statusReuse));
    UNREFERENCED_PARAMETER(statusReuse);

    RtlZeroMemory( &serverDeviceInfo, sizeof(serverDeviceInfo) );
    
    WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(
        &outMemDesc,
        &serverDeviceInfo,
        sizeof(serverDeviceInfo)
        );

    status = WdfIoTargetSendInternalIoctlSynchronously(
        DevCtx->Header.IoTarget,
        DevCtx->Header.Request,
        IOCTL_INTERNAL_BTHENUM_GET_DEVINFO,
        NULL,   //inMemDesc
        &outMemDesc,
        NULL,   //sendOptions
        NULL    //bytesReturned
        );

    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, 
            "Failed to obtain server device info, Status code %!STATUS!\n", status);

        goto exit;
    }

    DevCtx->ServerBthAddress = serverDeviceInfo.address;

exit:
    return status;
}
Пример #2
0
NTSTATUS
BthEchoCliRetrieveServerSdpRecord(
    __in PBTHECHOSAMPLE_CLIENT_CONTEXT DevCtx,
    __out PBTH_SDP_STREAM_RESPONSE * ServerSdpRecord    
    )
/*++

Description:

    Retrive server SDP record.
    We call this function on every file open to get the PSM

Arguments:

    DevCtx - Client context
    ServerSdpRecord - SDP record retrieved

Return Value:

    NTSTATUS Status code.

--*/
{
    NTSTATUS status, statusReuse, disconnectStatus;
    WDF_MEMORY_DESCRIPTOR inMemDesc;
    WDF_MEMORY_DESCRIPTOR outMemDesc;
    WDF_REQUEST_REUSE_PARAMS ReuseParams;    
    BTH_SDP_CONNECT connect = {0};
    BTH_SDP_DISCONNECT disconnect = {0};
    BTH_SDP_SERVICE_ATTRIBUTE_SEARCH_REQUEST requestSdp = {0};
    BTH_SDP_STREAM_RESPONSE responseSdp = {0};
    ULONG requestSize;
    PBTH_SDP_STREAM_RESPONSE serverSdpRecord = NULL;
    WDFREQUEST request;
    WDF_OBJECT_ATTRIBUTES attributes;
    

    PAGED_CODE();

    //
    // Allocate the request we will use for obtaining sdp record
    // NOTE that we do it for every file open, hence we
    //
    // can't use reserve request from the context
    //
    
    WDF_OBJECT_ATTRIBUTES_INIT(&attributes);

    status = WdfRequestCreate(
        &attributes,
        DevCtx->Header.IoTarget,
        &request
        );

    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, 
            "Failed to allocate request for retriving server sdp record, Status code %!STATUS!\n", status);

        goto exit;        
    }

    connect.bthAddress = DevCtx->ServerBthAddress;
    connect.requestTimeout = SDP_REQUEST_TO_DEFAULT;
    connect.fSdpConnect = 0;

    //
    // Connect to the SDP service.
    //

    WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(
        &inMemDesc,
        &connect,
        sizeof(connect)
        );
    
    WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(
        &outMemDesc,
        &connect,
        sizeof(connect)
        );

    status = WdfIoTargetSendIoctlSynchronously(
        DevCtx->Header.IoTarget,
        request,
        IOCTL_BTH_SDP_CONNECT,
        &inMemDesc,
        &outMemDesc,
        NULL,   //sendOptions
        NULL    //bytesReturned
        );

    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, 
            "IOCTL_BTH_SDP_CONNECT failed, Status code %!STATUS!\n", status);

        goto exit1;
    }

    //
    // Obtain the required size of the SDP record
    //
    requestSdp.hConnection = connect.hConnection;
    requestSdp.uuids[0].u.uuid128 = BTHECHOSAMPLE_SVC_GUID;
    requestSdp.uuids[0].uuidType = SDP_ST_UUID128;
    requestSdp.range[0].minAttribute = 0;
    requestSdp.range[0].maxAttribute = 0xFFFF;

    WDF_REQUEST_REUSE_PARAMS_INIT(&ReuseParams, WDF_REQUEST_REUSE_NO_FLAGS, STATUS_NOT_SUPPORTED);
    statusReuse = WdfRequestReuse(request, &ReuseParams);    
    ASSERT(NT_SUCCESS(statusReuse));
    UNREFERENCED_PARAMETER(statusReuse);

    WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(
        &inMemDesc,
        &requestSdp,
        sizeof(requestSdp)
        );
    
    WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(
        &outMemDesc,
        &responseSdp,
        sizeof(responseSdp)
        );

    status = WdfIoTargetSendIoctlSynchronously(
        DevCtx->Header.IoTarget,
        request,
        IOCTL_BTH_SDP_SERVICE_ATTRIBUTE_SEARCH,
        &inMemDesc,
        &outMemDesc,
        NULL,   //sendOptions
        NULL    //bytesReturned
        );

    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_SDP, 
            "IOCTL_BTH_SDP_SERVICE_ATTRIBUTE_SEARCH failed while querying response size, "
            "status code %!STATUS!\n", status);

        goto exit2;
    }

    //
    // Allocate the required size for SDP record
    //

    status = RtlULongAdd(
        responseSdp.requiredSize, 
        sizeof(BTH_SDP_STREAM_RESPONSE), 
        &requestSize
        );

    if(!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_SDP, 
            "SDP record size too large, status code %!STATUS!\n", status);

        goto exit2;
    }

    serverSdpRecord = ExAllocatePoolWithTag(NonPagedPool, requestSize, POOLTAG_BTHECHOSAMPLE);
    if (NULL == serverSdpRecord)
    {
        status = STATUS_INSUFFICIENT_RESOURCES;
        TraceEvents(TRACE_LEVEL_ERROR, DBG_SDP, 
            "Allocating SDP record failed, returning status code %!STATUS!\n", status); 

        goto exit2;
    }

    //
    // Send request with required size
    //
    
    WDF_REQUEST_REUSE_PARAMS_INIT(&ReuseParams, WDF_REQUEST_REUSE_NO_FLAGS, STATUS_NOT_SUPPORTED);
    statusReuse = WdfRequestReuse(request, &ReuseParams);    
    ASSERT(NT_SUCCESS(statusReuse));
    UNREFERENCED_PARAMETER(statusReuse);

    WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(
        &inMemDesc,
        &requestSdp,
        sizeof(requestSdp)
        );
    
    WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(
        &outMemDesc,
        serverSdpRecord,
        requestSize
        );

    status = WdfIoTargetSendIoctlSynchronously(
        DevCtx->Header.IoTarget,
        request,
        IOCTL_BTH_SDP_SERVICE_ATTRIBUTE_SEARCH,
        &inMemDesc,
        &outMemDesc,
        NULL,   //sendOptions
        NULL    //bytesReturned
        );

    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_SDP, 
            "IOCTL_BTH_SDP_SERVICE_ATTRIBUTE_SEARCH failed, status code %!STATUS!\n", status);

        ExFreePoolWithTag(serverSdpRecord, POOLTAG_BTHECHOSAMPLE);
    }
    else
    {
        *ServerSdpRecord = serverSdpRecord;
    }
    
exit2:
    
    //
    // Disconnect from SDP service.
    //
    
    WDF_REQUEST_REUSE_PARAMS_INIT(&ReuseParams, WDF_REQUEST_REUSE_NO_FLAGS, STATUS_NOT_SUPPORTED);
    statusReuse = WdfRequestReuse(request, &ReuseParams);    
    ASSERT(NT_SUCCESS(statusReuse));
    UNREFERENCED_PARAMETER(statusReuse);

    disconnect.hConnection = connect.hConnection;

    WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(
        &inMemDesc,
        &disconnect,
        sizeof(disconnect)
        );
    
    disconnectStatus = WdfIoTargetSendIoctlSynchronously(
        DevCtx->Header.IoTarget,
        request,
        IOCTL_BTH_SDP_DISCONNECT,
        &inMemDesc,
        NULL,   //outMemDesc
        NULL,   //sendOptions
        NULL    //bytesReturned
        );

    ASSERT(NT_SUCCESS(disconnectStatus)); //Disconnect should not fail

    if (!NT_SUCCESS(disconnectStatus))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, 
            "IOCTL_BTH_SDP_DISCONNECT failed, Status code %!STATUS!\n", status);
    }
    
exit1:    
    WdfObjectDelete(request);
exit:
    return status;
}
Пример #3
0
VOID
Toastmon_WriteRequestCompletionRoutine(
    IN WDFREQUEST                  Request,
    IN WDFIOTARGET                 Target,
    PWDF_REQUEST_COMPLETION_PARAMS CompletionParams,
    IN WDFCONTEXT                  Context
    )
/*++

Routine Description:

    Completion Routine

Arguments:

    CompletionParams - Contains the results of the transfer such as
                                    IoStatus, Length, Buffer, etc.

    Context - context value specified in the WdfRequestSetCompletionRoutine

Return Value:

    VOID

--*/
{
    WDF_REQUEST_REUSE_PARAMS    params;
    PTARGET_DEVICE_INFO       targetInfo;
    NTSTATUS status;

    UNREFERENCED_PARAMETER(Context);

    targetInfo = GetTargetDeviceInfo(Target);
    
    //
    // Delete the memory object because we create a new one every time we post
    // the request. For perf reason, it would be better to preallocate even memory object.
    // Also for driver created requests, do not call WdfRequestRetrieve functions to get
    // the buffers. WdfRequestRetrieveBuffer functions can be called only for requests
    // delivered by the queue.
    //
    WdfObjectDelete(CompletionParams->Parameters.Write.Buffer);

    //
    // Scrub the request for reuse.
    //
    WDF_REQUEST_REUSE_PARAMS_INIT(&params, WDF_REQUEST_REUSE_NO_FLAGS, STATUS_SUCCESS);

    status = WdfRequestReuse(Request, &params);
    ASSERT(NT_SUCCESS(status));

    //
    // RequestReuse zero all the values in structure pointed by CompletionParams.
    // So you must get all the information from completion params before
    // calling RequestReuse.
    //

    targetInfo->WriteRequest = Request;

    //
    // Don't repost the request in the completion routine because it may lead to recursion
    // if the driver below completes the request synchronously.
    //    
    return;
}
Пример #4
0
NTSTATUS
PowerContextReuseRequest(
    _In_ PCDROM_DEVICE_EXTENSION DeviceExtension
    )
/*++

Routine Description:

    reset fields for the request.

Arguments:

    DeviceExtension - device context

Return Value:

    NTSTATUS

--*/
{
    NTSTATUS                 status = STATUS_SUCCESS;
    WDF_REQUEST_REUSE_PARAMS reuseParams;
    PIRP                     irp = NULL;

    RtlZeroMemory(&(DeviceExtension->PowerContext.SenseData), sizeof(DeviceExtension->PowerContext.SenseData));
    RtlZeroMemory(&(DeviceExtension->PowerContext.Srb), sizeof(DeviceExtension->PowerContext.Srb));

    irp = WdfRequestWdmGetIrp(DeviceExtension->PowerContext.PowerRequest);

    // Re-use the previously created PowerRequest object and format it
    WDF_REQUEST_REUSE_PARAMS_INIT(&reuseParams, WDF_REQUEST_REUSE_NO_FLAGS, STATUS_NOT_SUPPORTED);
    status = WdfRequestReuse(DeviceExtension->PowerContext.PowerRequest, &reuseParams);
    if (NT_SUCCESS(status))
    {
        // This request was preformated during initialization so this call should never fail.
        status = WdfIoTargetFormatRequestForInternalIoctlOthers(DeviceExtension->IoTarget, 
                                                                DeviceExtension->PowerContext.PowerRequest,
                                                                IOCTL_SCSI_EXECUTE_IN,
                                                                NULL, NULL,
                                                                NULL, NULL,
                                                                NULL, NULL);

        if (!NT_SUCCESS(status))
        {
            TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_GENERAL,  
                       "PowerContextReuseRequest: WdfIoTargetFormatRequestForInternalIoctlOthers failed, %!STATUS!\n",
                       status));
        }
    }

    // Do some basic initialization of the PowerRequest, the rest will be done by the caller
    // of this function
    if (NT_SUCCESS(status))
    {
        PIO_STACK_LOCATION  nextStack = NULL;

        nextStack = IoGetNextIrpStackLocation(irp);

        nextStack->MajorFunction = IRP_MJ_SCSI;
        nextStack->Parameters.Scsi.Srb = &(DeviceExtension->PowerContext.Srb);

        DeviceExtension->PowerContext.Srb.Length = sizeof(SCSI_REQUEST_BLOCK);
        DeviceExtension->PowerContext.Srb.OriginalRequest = irp;

        DeviceExtension->PowerContext.Srb.SenseInfoBuffer = &(DeviceExtension->PowerContext.SenseData);
        DeviceExtension->PowerContext.Srb.SenseInfoBufferLength = SENSE_BUFFER_SIZE;
    }

    return status;
}
Пример #5
0
NTSTATUS
FORCEINLINE
BthEchoSharedSendBrbSynchronously(
    _In_ WDFIOTARGET IoTarget,
    _In_ WDFREQUEST Request,
    _In_ PBRB Brb,
    _In_ ULONG BrbSize
)
/*++

Routine Description:

    This routine formats a request with brb and sends it synchronously

Arguments:

    IoTarget - Target to send the brb to
    Request - request object to be formatted with brb
    Brb - Brb to be sent
    BrbSize - size of the Brb data structure

Return Value:

    NTSTATUS Status code.

Notes:

    This routine does calls WdfRequestReuse on the Request passed in.
    Caller need not do so before passing in the request.

    This routine does not complete the request in case of failure.
    Caller must complete the request in case of failure.

--*/
{
    NTSTATUS status;
    WDF_REQUEST_REUSE_PARAMS reuseParams;
    WDF_MEMORY_DESCRIPTOR OtherArg1Desc;

    WDF_REQUEST_REUSE_PARAMS_INIT(
        &reuseParams,
        WDF_REQUEST_REUSE_NO_FLAGS,
        STATUS_NOT_SUPPORTED
    );

    status = WdfRequestReuse(Request, &reuseParams);
    if (!NT_SUCCESS(status))
    {
        goto exit;
    }

    WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(
        &OtherArg1Desc,
        Brb,
        BrbSize
    );

    status = WdfIoTargetSendInternalIoctlOthersSynchronously(
                 IoTarget,
                 Request,
                 IOCTL_INTERNAL_BTH_SUBMIT_BRB,
                 &OtherArg1Desc,
                 NULL, //OtherArg2
                 NULL, //OtherArg4
                 NULL, //RequestOptions
                 NULL  //BytesReturned
             );

exit:
    return status;
}
Пример #6
0
NTSTATUS
BthEchoRepeatReaderSubmit(
    _In_ PBTHECHOSAMPLE_DEVICE_CONTEXT_HEADER DevCtxHdr,
    _In_ PBTHECHO_REPEAT_READER RepeatReader
    )
/*++

Description:

    This routine submits the repeat reader.

    In case of failure it invoked contreader failed callback

Arguments:

    DevCtxHdr - Device context header
    RepeatReader - Repeat reader to submit

Return Value:

    NTSTATUS Status code.

--*/
{
    NTSTATUS status, statusReuse;
    WDF_REQUEST_REUSE_PARAMS reuseParams;
    struct _BRB_L2CA_ACL_TRANSFER *brb = &RepeatReader->TransferBrb;    

    DevCtxHdr->ProfileDrvInterface.BthReuseBrb((PBRB)brb, BRB_L2CA_ACL_TRANSFER);

    WDF_REQUEST_REUSE_PARAMS_INIT(&reuseParams, WDF_REQUEST_REUSE_NO_FLAGS, STATUS_UNSUCCESSFUL);
    statusReuse = WdfRequestReuse(RepeatReader->RequestPendingRead, &reuseParams);
    NT_ASSERT(NT_SUCCESS(statusReuse));
    UNREFERENCED_PARAMETER(statusReuse);

    //
    // Check if we are stopping, if yes set StopEvent and exit.
    //
    // After this point request is eligible for cancellation, so if this
    // flag gets set after we check it, request will be cancelled for stopping
    // the repeat reader and next time around we will stop when we are invoked
    // again upon completion of cancelled request.
    //
    if (RepeatReader->Stopping)
    {
        TraceEvents(TRACE_LEVEL_INFORMATION, DBG_CONT_READER, 
            "Continuos reader 0x%p stopping", RepeatReader);        
        
        KeSetEvent(&RepeatReader->StopEvent, 0, FALSE);

        status = STATUS_SUCCESS;

        goto exit;
    }

    //
    // Format request for L2CA IN transfer
    //
    status = BthEchoConnectionObjectFormatRequestForL2CaTransfer(
        RepeatReader->Connection,
        RepeatReader->RequestPendingRead,
        &brb,
        RepeatReader->MemoryPendingRead,
        ACL_TRANSFER_DIRECTION_IN | ACL_SHORT_TRANSFER_OK
        );

    if (!NT_SUCCESS(status))
    {
        goto exit;
    }

    //
    // Set a CompletionRoutine callback function.
    //
    
    WdfRequestSetCompletionRoutine(
        RepeatReader->RequestPendingRead,
        BthEchoRepeatReaderPendingReadCompletion,
        RepeatReader
        );

    //
    // Clear the stop event before sending the request
    // This is relevant only on start of the repeat reader 
    // (i.e. the first submission)
    // this event eventually gets set only when repeat reader stops
    // and not on every resubmission.
    //
    KeClearEvent(&RepeatReader->StopEvent);

    if (FALSE == WdfRequestSend(
        RepeatReader->RequestPendingRead,
        DevCtxHdr->IoTarget,
        NULL
        ))
    {
        status = WdfRequestGetStatus(RepeatReader->RequestPendingRead);

        TraceEvents(TRACE_LEVEL_ERROR, DBG_CONT_READER, 
            "Request send failed for request 0x%p, Brb 0x%p, Status code %!STATUS!\n", 
            RepeatReader->RequestPendingRead,
            brb,
            status
            );

        goto exit;
    }
    else
    {
        TraceEvents(TRACE_LEVEL_INFORMATION, DBG_CONT_READER, 
            "Resubmited pending read with request 0x%p, Brb 0x%p", 
            RepeatReader->RequestPendingRead,
            brb
            );        
    }

exit:
    if (!NT_SUCCESS(status))
    {
        //
        // Invoke the reader failed callback before setting the event
        // to ensure that the connection object is alive during this callback
        //
        RepeatReader->Connection->ContinuousReader.BthEchoConnectionObjectContReaderFailedCallback(
            RepeatReader->Connection->DevCtxHdr, 
            RepeatReader->Connection
            );

        //
        // If we failed to send pending read, set the event since
        // we will not get completion callback
        //
            
        KeSetEvent(&RepeatReader->StopEvent, 0, FALSE);
    }
    
    return status;
}