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

📄 btsdp.cpp

📁 三星2440原版bsp
💻 CPP
📖 第 1 页 / 共 5 页
字号:
        return STATUS_INVALID_BUFFER_SIZE;
    }

    if (stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(BthSdpStreamResponse)) {
        return STATUS_INVALID_BUFFER_SIZE;
    }

    pSearch = (BthSdpServiceAttributeSearchRequest *) pIrp->AssociatedIrp.SystemBuffer;


    status = VerifyServiceSearch(pSearch->uuids, &maxUuids);
    if (!NT_SUCCESS(status)) {
        return status;
    }


    status =
        VerifyAttributeSearch(pSearch->range,
                              &maxRange,
                              stack->Parameters.DeviceIoControl.InputBufferLength -
                              (sizeof(*pSearch) - sizeof(pSearch->range))
                              );

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

    //
    // Check to see if this is a local search
    //
    if (pSearch->hConnection == HANDLE_SDP_LOCAL) {
        ULONG size;
        UCHAR *pResult;

        status = Globals.pSdpDB->ServiceSearchAttributeResponseLocal(
            pSearch->uuids,
            maxUuids,
            pSearch->range,
            maxRange,
            &pResult,
            &size);

        if (NT_SUCCESS(status)) {
            BthSdpStreamResponse *pResponse = (BthSdpStreamResponse *)
                pIrp->AssociatedIrp.SystemBuffer;

            ULONG responseSize;

            responseSize =
                stack->Parameters.DeviceIoControl.OutputBufferLength -
                (sizeof(*pResponse) - sizeof(pResponse->response));

            pResponse->requiredSize = size;
            if (responseSize < size) {
                info = responseSize;
            }
            else {
                info = size;
            }

            pResponse->responseSize = info;
            RtlCopyMemory(pResponse->response, pResult, info);
            info += (sizeof(*pResponse) - sizeof(pResponse->response));

            ExFreePool(pResult);
        }

        return status;
    }

    pCon = NULL;
    status = AcquireConnection(pSearch->hConnection, &pCon, pIrp);
    if (!NT_SUCCESS(status)) {
        return status;
    }

    //
    // Set the max range and uuids before we enqueue the request because the
    // send function assumes it is set (even for a queud irp processed at a
    // later time)
    //
    SetMaxUuidsInIrp(pIrp, maxUuids);
    SetMaxRangeInIrp(pIrp, maxRange);

    BOOLEAN added = pCon->clientQueue.AddIfBusy(pIrp, &status);

    if (added) {
        //
        // The queue is busy and the request has been queued.  Don't touch the 
        // irp anymore
        //
        return STATUS_PENDING;
    }
    else if (!NT_SUCCESS(status)) {
        //
        // The request was cancelled or something went wrong.  The irp was not 
        // enqueued.  Return the error status
        //
        pCon->ReleaseAndProcessNextRequest(pIrp);
        return status;
    }
    else {
        //
        // This is the current request on the connection, see if it matches the 
        // previous request
        //

        //
        // While we do not cache ServiceSearch responses, this will clean up 
        // any cached responsed from previous queries
        //
        status = pCon->IsPreviousRequest(pIrp,
                                         SdpPDU_ServiceSearchAttributeRequest,
                                         pSearch->uuids,
                                         pSearch->range,
                                         maxRange,
                                         &info);

        if (NT_SUCCESS(status) || status == STATUS_BUFFER_TOO_SMALL) {
            pCon->ReleaseAndProcessNextRequest(pIrp);
            return STATUS_SUCCESS;
        }
    }

    //
    // The actual transmission over the wire
    //
    return pCon->SendServiceSearchAttributeRequest(pIrp);
#endif // UNDER_CE    
}


#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
NTSTATUS SdpInterface::Disconnect(PIRP pIrp, ULONG_PTR& info)
{
    SdpConnection *pCon;
    NTSTATUS status;
    PVOID hConnection;
    LONG count = -1;
    PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);

    info = 0;

    if (stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(HANDLE)) {
        return STATUS_BUFFER_TOO_SMALL;
    }

    hConnection = *(HANDLE*) pIrp->AssociatedIrp.SystemBuffer;

    m_SdpConnectionList.Lock();

    pCon = FindConnection(hConnection);
    if (pCon) {
        if (pCon->IsClient()) {
            //
            // This will mark the connection as closing which will protect this
            // object from further connections until we remove it from the linked
            // list
            //
            count = pCon->RemoveFileObject(stack->FileObject);
        }
        else {
            //
            // We found a connection, but it is a server connection.  Spec says
            // that a server should not allow a disconnect except for extreme
            // conditions.
            //
            pCon = NULL;
        }
    }
    m_SdpConnectionList.Unlock();

    if (pCon) {
        if (count == -1) {
            //
            // Somehow the caller got the hConnection, but never called connect
            //
            status = STATUS_INVALID_PARAMETER;
        }
        else {
            //
            // count == 0, the object is going away
            //
            status = STATUS_SUCCESS;
        }
    }
    else {
        status = STATUS_DEVICE_NOT_CONNECTED;
    }

    if (NT_SUCCESS(status)) {
        pCon->Cleanup(stack->FileObject);

        if (count > 0) {
            //
            // There are still other clients using the underlying bth connection
            //
            return status;
        }

        BRB brb;

        RtlZeroMemory(&brb, sizeof(brb));

        brb.BrbHeader.Length = sizeof (_BRB_L2CA_DISCONNECT_REQ);
        brb.BrbHeader.Type = BRB_L2CA_DISCONNECT_REQ;
        brb.BrbHeader.Status = STATUS_SUCCESS;
        brb.BrbL2caDisconnectReq.hConnection = hConnection;

        //
        // Removed from the list in final cleanup
        //
        // m_SdpConnectionList.Lock();
        // m_SdpConnectionList.RemoveAt(pCon);
        // m_SdpConnectionList.Unlock();

        //
        // pCon will be deleted in the IndicationFinalCleanup handler
        //
        status = SendBrb(&brb);
    }

    return status;
}

void
SdpInterface::CloseConnections(
    PIRP pIrp
    )
{
    PFILE_OBJECT pFileObject = IoGetCurrentIrpStackLocation(pIrp)->FileObject;

    m_SdpConnectionList.Lock();
    m_SdpConnectionList.Unlock();
}
#endif // UNDER_CE

NTSTATUS
CrackContState(
    IN OUT PUCHAR &pStream,
    IN OUT ULONG  &streamSize,
    OUT ContinuationState *pContState,
    OUT PSDP_ERROR pSdpError
    )
{
    // PAGED_CODE();

    BOOLEAN res = pContState->Read(pStream, streamSize);

    if (res == FALSE) {
        //
        // spec says, max cont state is 16 bytes long.  We get the streamSize 
        // from the pdu parameter length field so this is actually an error in
        // that field, not an error in the continuation state.
        //
        *pSdpError = SDP_ERROR_INVALID_PDU_SIZE; 
        return STATUS_INVALID_PARAMETER;
    }
    
    //
    // one for the header + actual state info
    //
    pStream += (1 + pContState->size);
    streamSize -= (1 + pContState->size);

    ASSERT(streamSize == 0);

    return STATUS_SUCCESS;
}

NTSTATUS
CrackSequenceParameter(
    IN OUT PUCHAR &pStream,
    IN OUT ULONG  &streamSize,
    IN     ULONG  minRemainingStream,
       OUT ULONG *pSequenceSize
    )
{
    // PAGED_CODE();

    UCHAR type, sizeIndex;

    SdpRetrieveHeader(pStream, type, sizeIndex);

    if (type != (UCHAR) SDP_TYPE_SEQUENCE) {
        return STATUS_INVALID_PARAMETER; 
    }

    if (sizeIndex < 5 || sizeIndex > 7) {
        return STATUS_INVALID_PARAMETER; 
    }

    pStream++;
    streamSize--;

    ULONG elementSize, storageSize;
    SdpRetrieveVariableSize(pStream, sizeIndex, &elementSize, &storageSize);

    if (elementSize + storageSize >= streamSize + minRemainingStream) {
        return STATUS_INVALID_PARAMETER; 
    }

    *pSequenceSize = 1 + storageSize + elementSize;

    //
    // We have incremented past the header above, so decrement back
    //
    NTSTATUS status = ValidateStream(pStream-1,     
                                     *pSequenceSize,
                                     NULL,
                                     NULL,
                                     NULL);

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

    pStream += (storageSize + elementSize);
    streamSize -= (storageSize + elementSize);

    return STATUS_SUCCESS;
}

NTSTATUS 
SdpInterface::CrackClientServiceSearchRequest(
    IN UCHAR *pServiceSearchRequestStream,
    IN ULONG streamSize,
    OUT UCHAR **ppSequenceStream,
    OUT ULONG *pSequenceStreamSize,
    OUT USHORT *pMaxRecordCount,
    OUT ContinuationState *pContState,
    OUT PSDP_ERROR pSdpError
    )
{
    // PAGED_CODE();

    UCHAR *pStream;
     
    //
    // data elem sequence        = 2 =  1 (seq hdr) + 1 (seq size)
    //                           = 3 =  1 (elem hdr) + 2 (size of uuid16)
    // sizeof(max record count)  = 2
    // cont state               >= 1
    //
    if (streamSize < 8) {
        *pSdpError = MapNtStatusToSdpError(STATUS_INVALID_PARAMETER);
        return STATUS_INVALID_PARAMETER;
    }

    pStream = pServiceSearchRequestStream;

    //
    // 3 = sizeof(max record count) + at least one for cont state
    // 
    NTSTATUS status;
     
    *ppSequenceStream = pStream;
    status =
        CrackSequenceParameter(pStream, streamSize, 3, pSequenceStreamSize);

    if (!NT_SUCCESS(status)) {
        *pSdpError = MapNtStatusToSdpError(STATUS_INVALID_PARAMETER);
        return STATUS_INVALID_PARAMETER;
    }

    RtlRetrieveUshort(pMaxRecordCount, pStream);
    *pMaxRecordCount = RtlUshortByteSwap(*pMaxRecordCount);

    pStream += sizeof(USHORT); 
    streamSize -= sizeof(USHORT);

    return CrackContState(pStream, streamSize, pContState, pSdpError);
}

NTSTATUS 
SdpInterface::CrackClientServiceAttributeRequest(
    IN UCHAR *pServiceAttributeRequestStream,
    IN ULONG streamSize,
    OUT ULONG *pRecordHandle,
    OUT USHORT *pMaxAttribByteCount,
    OUT UCHAR **ppAttribIdListStream,
    OUT ULONG *pAttribIdListStreamSize,
    OUT ContinuationState *pContState,
    OUT PSDP_ERROR pSdpError
    )
{
    // PAGED_CODE();

    //
    // record handle         = 4
    // max attrib byte count = 2
    // id list (seq)         = 2 = 1 (seq header) + 1 (stream size)
    //                       = 3 = 1 (elem hdr) + 2 (size of ushort)
    // cont state            = 1
    // 
    if (streamSize < 12) {
        *pSdpError = MapNtStatusToSdpError(STATUS_INVALID_PARAMETER);
        return STATUS_INVALID_PARAMETER;
    }

    UCHAR *pStream;

    pStream = pServiceAttributeRequestStream;

    RtlRetrieveUlong(pRecordHandle, pStream);
    *pRecordHandle = RtlUlongByteSwap(*pRecordHandle);

    pStream += sizeof(ULONG);
    streamSize -= sizeof(ULONG);

    RtlRetrieveUshort(pMaxAttribByteCount, pStream);
    *pMaxAttribByteCount = RtlUshortByteSwap(*pMaxAttribByteCount);


    pStream += sizeof(USHORT);
    streamSize -= sizeof(USHORT);

    //
    // 1 = cont state
    //
    NTSTATUS status;
    
    *ppAttribIdListStream = pStream;
    status =
        CrackSequenceParameter(pStream, streamSize, 1, pAttribIdListStreamSize);

    if (!NT_SUCCESS(status)) {
        *pSdpError = MapNtStatusToSdpError(STATUS_INVALID_PARAMETER);
        return STATUS_INVALID_PARAMETER;
    }

    return CrackContState(pStream, streamSize, pContState, pSdpError);
}

NTSTATUS 
SdpInterface::CrackClientServiceSearchAttributeRequest(
    IN UCHAR *pServiceSearchAttributeRequestStream,
    IN ULONG streamSize,
    OUT UCHAR **ppServiceSearchSequence,
    OUT ULONG *pServiceSearchSequenceSize,
    OUT USHORT *pMaxAttributeByteCount,
    OUT UCHAR **ppAttributeIdSequence,
    OUT ULONG *pAttributeIdSequenceSize,
    OUT ContinuationState *pContState,
    OUT PSDP_ERROR pSdpError
    )
{
    // PAGED_CODE();

    //
    // uuid elem sequence        = 2 =  1 (seq hdr) + 1 (seq size)
    //                           = 3 =  1 (elem hdr) + 2 (size of uuid16)
    // max attrib byte count     = 2
    // attrib elem sequence      = 2 =  1 (seq hdr) + 1 (seq size)
    //                           = 3 =  1 (elem hdr) + 2 (size of uuid16)
    // cont state                = 1
    //
    if (streamSize < 13) {
        *pSdpError = MapNtStatusToSdpError(STATUS_INVALID_PARAMETER);
        return STATUS_INVALID_PARAMETER;
    }

    NTSTATUS status;
    UCHAR *pStream;

    pStream = pServiceSearchAttributeRequestStream;

⌨️ 快捷键说明

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