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

📄 sdpdb.cpp

📁 三星2440原版bsp
💻 CPP
📖 第 1 页 / 共 3 页
字号:
    status = SdpTreeFromStream(pStream, streamSize, NULL, &tree, TRUE);
    if (!NT_SUCCESS(status)) {
        return status; 
    }
    ASSERT(tree != NULL);

#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
    // WinCE has added ability to update record handle (pRecord != NULL)
    ULONG recordHandle = GetNextRecordHandle();
#else
    ULONG recordHandle = pRecordOriginal ? pRecordOriginal->recordHandle : GetNextRecordHandle();
#endif

    uint32 = SdpCreateNodeUInt32(recordHandle);
    if (uint32 == NULL) {
        //
        // see if we can roll back the increment.  This will not recover the 
        // "acquired" recordHandle if another caller has tried to add a record in
        // between our call for GetNextRecordHandle and here
        //
        status = STATUS_INSUFFICIENT_RESOURCES;
        goto Done;
    }

    SdpAddAttributeToTree(tree, SDP_ATTRIB_RECORD_HANDLE, uint32);

#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
    //
    // Only automatically add the public browse group list if the user does NOT
    // disable this feature.
    //
    if ((fOptions & SERVICE_OPTION_NO_PUBLIC_BROWSE) == 0 &&
        (fOptions & SERVICE_OPTION_DO_NOT_PUBLISH) == 0) {
        pCont = NULL;
        status = SdpFindAttributeInTree(tree,
                                        SDP_ATTRIB_BROWSE_GROUP_LIST,
                                        &pCont);

        if (NT_SUCCESS(status)) {
            // 
            // Group was present
            //
            /* do nothing */;
        }
        else {
            PSDP_NODE pSeq, pUuid16;
             
            ASSERT(pCont == NULL);

            //
            // Group was not present, add it
            //
            // Keep status as a failure code until we successfully add the
            // attribute
            //
            pSeq = SdpCreateNodeSequence();

            if (pSeq) {
                pUuid16 =
                    SdpCreateNodeUUID16(PublicBrowseGroupServiceClassID_UUID16);

                if (pUuid16) {
                    //
                    // Add in the node and set our status to success
                    //
                    SdpAppendNodeToContainerNode(pSeq, pUuid16);
                    SdpAddAttributeToTree(tree,
                                          SDP_ATTRIB_BROWSE_GROUP_LIST,
                                          pSeq);
                    status = STATUS_SUCCESS;
                }
                else {
                    SdpFreeOrphanedNode(pSeq);
                }
            }
        }
    }

    if (!NT_SUCCESS(status)) {
        goto Done;
    }   
#endif // UNDER_CE

    //
    // See if there is a protocol list.  Some records, such as the BrowseGroupInfo
    // will not have any protocols associated with them
    //
    status = SdpFindAttributeInTree(tree, SDP_ATTRIB_PROTOCOL_DESCRIPTOR_LIST, &pCont);
    if (NT_SUCCESS(status)) {
        ASSERT(pCont != NULL);

        if (pCont->hdr.Type == SDP_TYPE_ALTERNATIVE) {
            count = 0;
            PLIST_ENTRY entry = pCont->u.alternative.Link.Flink;
            for ( ; entry != &pCont->u.alternative.Link; entry = entry->Flink, count++) 
                ;

            ASSERT(count != 0);
        }
        else {
            ASSERT(pCont->hdr.Type == SDP_TYPE_SEQUENCE);
            count = 1;
        }
    }
    else {
        status = STATUS_SUCCESS;
        count = 0;
    }

    size = sizeof(ServiceRecord);
    if (count > 1) {
        size += sizeof(PSM_PROTOCOL_PAIR) * (count - 1);
    }

#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))    
        pv = ExAllocatePoolWithTag(NonPagedPool, size, SDP_TAG);

    if (pv) {
        pRecord = new(pv) ServiceRecord;
    }
    else {
        status = STATUS_INSUFFICIENT_RESOURCES;
        goto Done;
    }

    if (count && pCont) {
        //
        // This will also initialize the psmList
        //
        status = SdpValidateProtocolContainer(pCont, &pRecord->psmList);
        if (!NT_SUCCESS(status)) {
            goto Done;
        }
    }
#else
    pRecord = new ServiceRecord();
    if (!pRecord) {
        status = STATUS_INSUFFICIENT_RESOURCES;
        goto Done;
    }
#endif

    //
    // Get the service class ID.  This is a sequence of UUIDs, where the 1st
    // item in the list is the most specific.  SdpVerifyServiceRecord has made
    // sure that this attrib exists
    //
    SdpFindAttributeInTree(tree, SDP_ATTRIB_CLASS_ID_LIST, &pCont);
    ASSERT(pCont != NULL);
    ASSERT(pCont->hdr.Type == SDP_TYPE_SEQUENCE);
    ASSERT(!IsListEmpty(&pCont->u.sequence.Link));

    //
    // Store the UUID as a 128 bit UUID to make comparison easier
    //
    SdpNormalizeUuid(
        CONTAINING_RECORD(pCont->u.sequence.Link.Flink, SDP_NODE, hdr.Link),
        &pRecord->serviceClass);

#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
    serviceClass = pRecord->serviceClass;

    //
    //  Allow each validator to validate stream
    //
    status = ValidateRecordExternal(pStream,
                                    streamSize,
                                    tree,
                                    &pRecord->psmList,
                                    RVF_ADD_RECORD,
                                    &pRecord->serviceClass
                                    );
#endif // UNDER_CE                                    

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


    status = SdpStreamFromTree(tree, &pNewStream, &newStreamSize);
    if (!NT_SUCCESS(status)) {
        goto Done; 
    }


//
// don't know if this chunk of code is necessary or not
//
#if 0
    //
    // Revalidate in case one of the validators failed
    //
    status = SdpIsStreamRecord(pNewStream, newStreamSize);
    if (!NT_SUCCESS(status)) {
         goto Done;
    }

    //
    // Make sure all of the universal attributes have the correct syntax and 
    // that all of the attributes we require locally are present
    //
    err = 0xFFFF;
    status = SdpVerifyServiceRecord(pNewStream,
                                    newStreamSize, 
                                    VERIFY_CHECK_MANDATORY_LOCAL,
                                    &err);
    if (!NT_SUCCESS(status)) {
        goto Done;
    }
#endif

    m_ServiceRecordList.Lock();

#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
    ProtMux *ppm;
    ULONG i; // ,j
    protIsMux = FALSE;

    for (i = 0; i < pRecord->psmList.count; i++) {
        if ((protIsMux = IsProtocolMuxed(pRecord->psmList.list[i].protocol))) {
            break;
        }
    }

    if (protIsMux == FALSE) {
        //
        // Make sure the protocol isn't duplicated across any other record
        //
        ServiceRecord *psr;

        for (psr = m_ServiceRecordList.GetHead();
             psr != NULL;
             psr = m_ServiceRecordList.GetNext(psr)) {

            for (i = 0; i < psr->psmList.count; i++) {
                for (j = 0; j < pRecord->psmList.count; j++) {
                    //
                    // We only care about potential conflicts on the PSM
                    //
                    if (psr->psmList.list[i].psm == pRecord->psmList.list[j].psm) {
                        if (IsEqualUuid(&psr->psmList.list[i].protocol,
                                        &pRecord->psmList.list[j].protocol)) {
                            //
                            // protocol is being muxed w/out a registered mux handler
                            //
                            status = STATUS_DEVICE_PROTOCOL_ERROR;
                        }
                        else {
                            //
                            // different protocols on top of the same PSM
                            //
                            status = STATUS_NO_MATCH;
                        }

                        break;
                    }
                }

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

            if (!NT_SUCCESS(status)) {
                break;
            }
        }
    }
#endif // UNDER_CE

    if (NT_SUCCESS(status)) {
        //
        // Make sure the psmList in this record is either unique, or we have a
        // registered multiplexor for it
        //

#if defined (UNDER_CE) || defined (WINCE_EMULATION)
        if (pRecordOriginal)  {
            if (pRecordOriginal->pStream)
                SdpFreePool(pRecordOriginal->pStream);

            memcpy(&pRecordOriginal->serviceClass,&pRecord->serviceClass,sizeof(GUID));
            ASSERT(pRecordOriginal == pRecordOriginal->handle);
            ASSERT(pRecordOriginal->recordHandle == recordHandle);

            delete pRecord;
            pRecord = pRecordOriginal;
        }

        pRecord->recordHandle = recordHandle;
        pRecord->streamSize = newStreamSize;
        pRecord->pStream = pNewStream;
        pRecord->psmList.count = 0;

        AlterDatabaseState();

        if (!pRecordOriginal)
            m_ServiceRecordList.AddTail(pRecord);
#if defined (UNDER_CE)
        *pHandle = pRecord->handle = (HANDLE) pRecord;
#endif

#else   // UNDER_CE
        pRecord->recordHandle = recordHandle;
        pRecord->streamSize = newStreamSize;
        pRecord->fService = fService;
        pRecord->fOptions = fOptions;
        pRecord->pFileObject = stack->FileObject;
        pRecord->pStream = pNewStream;
        pRecord->handle = (HANDLE) pRecord;

        AlterDatabaseState();

        m_ServiceRecordList.AddTail(pRecord);
#endif  // UNDER_CE
    }

    m_ServiceRecordList.Unlock();

Done:
    if (tree) {
        SdpFreeTree(tree);
    }

    if (NT_SUCCESS(status)) {
#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
        FireWmiEvent(*pHandle, SdpDatabaseEventNewRecord);
        Globals.pSecDB->AddService(serviceClass, fSecurity);
        *pfService = fService;
#endif
    }
    else {
        if (pRecord) {
            delete pRecord;
        }

        if (pNewStream) {
            SdpFreePool(pNewStream);
        }

        //
        // this will revert the next record handle count if there have been 
        // no new records in between the increment and here.  Otherwise, it will
        // be a gap
        //
#if defined (UNDER_CE)
        InterlockedCompareExchange(&m_nextRecordHandle,
                                   (LONG)(recordHandle-1),
                                   (LONG) recordHandle);
#else
        InterlockedCompareExchange((void **)&m_nextRecordHandle,
                                   (void *)(recordHandle-1),
                                   (void *) recordHandle);
#endif
    }

    return status;
}

NTSTATUS SdpDatabase::UpdateRecord(UCHAR *pStream, ULONG stremaSize, HANDLE handle)
{
#if (defined (UNDER_CE) || defined (WINCE_EMULATION))
    ServiceRecord *pRecordOriginal;
    NTSTATUS status;

    if (handle == 0) {
    	ASSERT(0); // handle == 0 only for SDP specific database entry.  Should never get in this state
		return STATUS_NOT_FOUND;
    }
 
    // make sure record is in the data base.
    m_ServiceRecordList.Lock();
    for (pRecordOriginal = m_ServiceRecordList.GetHead();
         pRecordOriginal != NULL;
         pRecordOriginal = m_ServiceRecordList.GetNext(pRecordOriginal)) {
        if (pRecordOriginal->handle == handle) {
            break;
        }
    }

    if (!pRecordOriginal) {
        m_ServiceRecordList.Unlock();
        return STATUS_NOT_FOUND;
    }

    status = AddRecord(pStream,stremaSize,&handle,pRecordOriginal);
    m_ServiceRecordList.Unlock();
    return status;

#else // UNDER_CE
    // This code isn't fully implemented on NT yet.
    if (handle == INVALID_ID) {
        return STATUS_INVALID_PARAMETER;
    }

    //
    // Find the record in the list, then remove it.  If the update
    // goes well, it will be reinserted into the list.  I remove it so
    // I can make calls outside the driver without holding onto a lock
    //
    ServiceRecord *pRecord;
    NTSTATUS status = STATUS_NOT_FOUND;

#if 0
    m_ServiceRecordList.Lock();
    for (pRecord = m_ServiceRecordList.GetHead();
         pRecord != NULL;
         pRecord = m_ServiceRecordList.GetNext(pRecord)) {
        
        if (pRecord->handle == handle) {
            m_ServiceRecordList.RemoveAt(pRecord);
            status = STATUS_SUCCESS;
            break;
        }
    }

    m_ServiceRecordList.Unlock();
#endif

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

    //
    // TBD:  of the core attributes, what do we allow to change?
    // o RecordHandle ? defnitely not
    // o ServiceClass ?  if so, then the record is more "new" than updated
    // o 
    //
    FireWmiEvent(handle, SdpDatabaseEventUpdateRecord);

    return status;
#endif 
}



NTSTATUS
SdpDatabase::RemoveRecord(
    HANDLE handle,
    ULONG *pfService
    )
{
    if ((handle == INVALID_ID) || (handle == 0)) {
        return STATUS_INVALID_PARAMETER;
    }

    ServiceRecord *pRecord;
    NTSTATUS status = STATUS_NOT_FOUND;

    m_ServiceRecordList.Lock();
    for (pRecord = m_ServiceRecordList.GetHead();
         pRecord != NULL;
         pRecord = m_ServiceRecordList.GetNext(pRecord)) {
        
        if (pRecord->handle == handle) {
            m_ServiceRecordList.RemoveAt(pRecord);
            AlterDatabaseState();
            status = STATUS_SUCCESS;
            break;
        }
    }

    m_ServiceRecordList.Unlock();

    if (NT_SUCCESS(status)) {
        FireWmiEvent(handle, SdpDatabaseEventRemoveRecord);
#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
        *pfService = pRecord->fService;
#endif
        delete pRecord;
    }

    return status;
}

#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
void SdpDatabase::Cleanup(PFILE_OBJECT pFileObject)
{
    ServiceRecordList sdl;

    ServiceRecord *pRecord;

    m_ServiceRecordList.Lock();

    pRecord = m_ServiceRecordList.GetHead();
    while (pRecord != NULL) {
        
        if (pRecord->pFileObject == pFileObject) {
            //
            // Retrieve the next record in the list b/c we will lose the link
            // once it pRecord is removed from the list
            //
            ServiceRecord *pNext = m_ServiceRecordList.GetNext(pRecord);
            m_ServiceRecordList.RemoveAt(pRecord);
            sdl.AddTail(pRecord);
            pRecord = pNext;
        }
        else {
            pRecord = m_ServiceRecordList.GetNext(pRecord);
        }
    }

    if (!sdl.IsEmpty()) {
        AlterDatabaseState();
    }

    m_ServiceRecordList.Unlock();

⌨️ 快捷键说明

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