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

📄 sdprecord.cpp

📁 三星2440原版bsp
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
// SdpRecord.cpp : Implementation of CSdpRecord
#include "stdafx.h"
#include "BthAPI.h"
#include "sdplib.h"
#include "SdpNodeList.h"
#include "SdpRecord.h"
#include "util.h"
#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
#include <mlang.h>
#include <assert.h>

struct MIBEnumToCharset {
    USHORT mibeNum;
    WCHAR* pszCharset;
};

//
// MIBE numbers came from iana website
//      (http://www.isi.edu/in-notes/iana/assignments/character-sets)
//
// matching string names were manually matched from the iana site in the table
//  in nt\shell\ext\mlan\mimedb.cpp
//
const MIBEnumToCharset g_MibeMapping[] = {
    {3,  L"us-ascii"},      // ascii
    {4,  L"iso-8859-1"},    // latin
    {5,  L"iso-8859-2"},    // latin2
    {6,  L"iso-8859-3"},    // latin3
    {7,  L"iso-8859-4"},    // latin4
    {8,  L"iso-8859-5"},    // latin cyrillic
    {9,  L"iso-8859-6"},    // arabic
    {10, L"iso-8859-7"},    // latin greek
    {11, L"iso-8859-8"},    // latin hebrew
    {12, L"iso-8859-9"},    // latin5
    {17, L"ms_Kanji"},      // kanji / japanese
    {18, L"euc-jp"},     
    {19, L"Extended_UNIX_Code_Packed_Format_for_Japanese"}, 
    {25, L"NS_4551-1"},     // danish, norwegian
    {36, L"iso-ir-149"},    // korean
    {37, L"iso-2022-kr" },  // korean
    {38, L"euc-kr" },       // korean
    {39, L"iso-2022-jp" },  // japanese
    {40, L"iso-2022-jp" },  // L"iso-2022-jp-2" really, but no match in IMultiLanguage
    {45, L"csISOLatinGreek" },
    {57, L"GB_2312-80"},
    {85, L"ISO_8859-8-I"},
    {103, L"unicode-1-1-utf-7"},
    {106, L"utf-8"},
    {109, L"iso-8859-13"},
    {111, L"iso-8859-15"},
    {1010, L"csUnicode11"},
    {1012, L"utf-7"},
    {1013, L"UTF-16BE"},
    {1014, L"UTF-16LE"},
    {1015, L"utf-16"},
    {2009, L"ibm850"},
    {2010, L"ibm852"},
    {2011, L"IBM437"},
    {2024, L"csWindows31J"},      
    {2025, L"GB2312"},      // PRC mixed set
    {2026, L"Big5"},        // Chinese for taiwan mb set 
    {2027, L"macintosh"},
    {2028, L"ebcdic-cp-us"},
    {2047, L"ibm857"},
    {2049, L"ibm861"},
    {2054, L"ibm869"},
    {2084, L"koi8-r"},
    {2085, L"hz-gb-2312"},
    {2086, L"ibm866"},
    {2087, L"ibm775"},
    {2088, L"koi8-u"},
    {2250, L"windows-1250"},
    {2251, L"windows-1251"},
    {2252, L"windows-1252"},
    {2253, L"windows-1253"},
    {2253, L"windows-1253"},
    {2254, L"windows-1254"},
    {2255, L"windows-1255"},
    {2256, L"windows-1256"},
    {2257, L"windows-1257"},
    {2258, L"windows-1258"},
    {2259, L"TIS-620"},
};

const ULONG g_MibeMappingCount = sizeof(g_MibeMapping) / sizeof(g_MibeMapping[0]);
#endif // UNDER_CE

#define LOCK_LIST() ListLock l(&listLock)

#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
WCHAR* FindCharset(USHORT mibeNum)
{
    ULONG iStart = 0, iEnd = g_MibeMappingCount-1, iMiddle;

    //
    // Binary search through the array (sorted by mibeNum)
    //
    while (iStart <= iEnd) {
        iMiddle = (iStart + iEnd) / 2;
        if (mibeNum == g_MibeMapping[iMiddle].mibeNum) {
            return g_MibeMapping[iMiddle].pszCharset;
        }
        else if (mibeNum > g_MibeMapping[iMiddle].mibeNum) {
            iStart = iMiddle + 1;
        }
        else {
            iEnd = iMiddle - 1;
        }
    }

    return NULL;
}
#endif



/////////////////////////////////////////////////////////////////////////////
// CSdpRecord

void CSdpRecord::Init(void)
{
#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
    m_pUnkMarshaler = NULL;
#endif    
    locked = 0;

    InitializeCriticalSection(&listLock);
}

CSdpRecord::~CSdpRecord()
{
    DeleteCriticalSection(&listLock);
    DestroyRecord();
}

void CSdpRecord::LockRecord(UCHAR lock)
{
    LOCK_LIST();

    if (lock) {
        locked++;
    }
    else {
        lock--;
    }

    nodeList.Lock(lock);
}

void CSdpRecord::DestroyRecord(void)
{
    nodeList.Destroy(); 
}

STDMETHODIMP CSdpRecord::CreateFromStream(UCHAR *pStream, ULONG size)
{
    NTSTATUS status;

    if (pStream == NULL) {
        return E_POINTER;
    }

    //
    // validate the format of the stream
    //
    status = SdpIsStreamRecord(pStream, size);
    if (!NT_SUCCESS(status)) {
        return E_INVALIDARG;
    }

    //
    // make sure that each attribute is of the correct format
    //
    USHORT attribId = 0xFFFF;
    status = SdpVerifyServiceRecord(pStream, size, 0, &attribId);
    if (!NT_SUCCESS(status)) {
        return E_INVALIDARG;
    }

    UCHAR type, sizeIndex;

    SdpRetrieveHeader(pStream, type, sizeIndex);
    pStream++;

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

    if (locked) {
        return E_ACCESSDENIED;
    }

    HRESULT err;

    if (elementSize > 0) {

        DestroyRecord();

        err = nodeList.CreateFromStream(pStream + storageSize, elementSize);

        if (!SUCCEEDED(err)) {
            DestroyRecord();
        }
    }
    else {
        err = S_OK;
    }

	return err;
}

STDMETHODIMP CSdpRecord::WriteToStream(
    UCHAR **ppStream,
    ULONG *pStreamSize,
    ULONG preSize,
    ULONG postSize
    )
{
    if (ppStream == NULL || pStreamSize == NULL) {
        return E_POINTER;
    }

    HRESULT err = S_OK;

    LockRecord(TRUE);
    
    ULONG streamSize, size;
    streamSize = nodeList.GetStreamSize();
    size = streamSize + GetContainerHeaderSize(streamSize);

    PUCHAR stream = (PUCHAR) CoTaskMemAlloc(size + preSize + postSize);
    if (stream) {
        *ppStream = stream;
        *pStreamSize = size;

        ZeroMemory(*ppStream, size + preSize + postSize);

        stream = WriteVariableSizeToStream(SDP_TYPE_SEQUENCE, streamSize, stream + preSize);
        nodeList.WriteStream(stream);
    }

    LockRecord(FALSE);

	return err;
}

STDMETHODIMP CSdpRecord::SetAttribute(USHORT attribute, NodeData *pData)
{
    PSDP_NODE pNode = NULL;

    //
    // pData == NULL signifies removal
    //
    if (pData != NULL) {
        HRESULT err = CreateSdpNodeFromNodeData(pData, &pNode);
        if (!SUCCEEDED(err)) {
            return err;
        }

#if 0
        //
        // Check its format.  For universal attributes, we know the format of the 
        // attribute, so convert this node to a stream and see if it is the correct
        // one
        //
        // Only check if we know the format
        //
        if (attribute <= 0x200) {
            PSDP_NODE pTree;
            PUCHAR stream;
            ULONG size;
            NTSTATUS status;

            pTree = SdpCreateNodeTree();
            if (pTree == NULL) {
                SdpFreeOrphanedNode(pNode);
                return E_OUTOFMEMORY;
            }


            status = SdpAppendNodeToContainerNode(pTree, pNode);
            if (!NT_SUCCESS(status)) {
                SdpFreeOrphanedNode(pNode);
                SdpFreeTree(pTree);
                return MapNtStatusToHresult(status);
            }

            status = SdpStreamFromTree(pTree, &stream, &size);

            if (!NT_SUCCESS(status)) {
                //
                // no need to free the orphan b/c it is now a part of the tree
                //
                SdpFreeTree(pTree);
                return MapNtStatusToHresult(status);
            }

            //
            // verify the attribute value
            //
            status = SdpVerifyServiceRecord(stream,
                                            size,
                                            VERIFY_STREAM_IS_ATTRIBUTE_VALUE,
                                            &attribute);

            SdpFreePool(stream);
            stream = NULL;

            if (!NT_SUCCESS(status)) {
                SdpFreeTree(pTree);
                return MapNtStatusToHresult(status);
            }

            //
            // Get the node out of the linked list so we can insert it into the
            // nodeList
            //
            PLIST_ENTRY entry = Sdp_RemoveHeadList(&pTree->hdr.Link);
            pNode = CONTAINING_RECORD(entry, SDP_NODE, hdr.Link);

            Sdp_InitializeListHead(&pNode->hdr.Link);

            //
            // don't need the tree root anymore
            //
            SdpFreeTree(pTree);
        }
#endif // 0
    }

    LOCK_LIST();

    if (locked) {
        return E_ACCESSDENIED;
    }

//  NTSTATUS status = SdpAddAttributeToTree((PSDP_NODE) &nodeList, attribute, pNode);
    NTSTATUS status = SdpAddAttributeToNodeHeader(&nodeList, attribute, pNode);

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

    //
    // successful remove, maintain the node count (id and value are now gone)
    //
    if (pNode == NULL) {
        nodeList.nodeCount -= 2;
    }

	return S_OK;
}

STDMETHODIMP CSdpRecord::SetAttributeFromStream(USHORT attribute, UCHAR *pStream, ULONG size)
{
    PSDP_NODE pNode = NULL;

    if (!NT_SUCCESS(ValidateStream(pStream, size, NULL, NULL, NULL))) {
        return E_INVALIDARG;
    }

    if (!NT_SUCCESS(SdpVerifyServiceRecord(pStream,
                                           size,
                                           VERIFY_STREAM_IS_ATTRIBUTE_VALUE,
                                           &attribute))) {
        return E_INVALIDARG;
    }

    LOCK_LIST();

    if (locked) {
        return E_ACCESSDENIED;
    }

    //
    // if pStream or size are 0, then the caller wants to remove the attribute
    //
    if (pStream != NULL && size != 0) {
        SdpNodeList tmpList;
        HRESULT err;

        err = tmpList.CreateFromStream(pStream, size);
        if (!SUCCEEDED(err)) {
            return err;
        }

        //
        // Attribute values can be just one element, whether it be a uint or a
        // container
        //
        if (tmpList.nodeCount != 1) {
            return E_INVALIDARG;
        }

        PLIST_ENTRY entry = Sdp_RemoveHeadList(&tmpList.Link);
        pNode = CONTAINING_RECORD(entry, SDP_NODE, hdr.Link);

        Sdp_InitializeListHead(&pNode->hdr.Link);
    }

//  NTSTATUS status = SdpAddAttributeToTree((PSDP_NODE) &nodeList, attribute, pNode);
    NTSTATUS status = SdpAddAttributeToNodeHeader(&nodeList, attribute, pNode);

    if (!NT_SUCCESS(status)) {
        SdpFreeOrphanedNode(pNode);
        return MapNtStatusToHresult(status);
    }

    //
    // successful remove, maintain the node count (id and value are now gone)
    //
    if (pNode == NULL) {
        nodeList.nodeCount -= 2;
    }

	return S_OK;
}

PSDP_NODE CSdpRecord::GetAttributeValueNode(USHORT attribute)
{
    PLIST_ENTRY current = nodeList.Link.Flink;

    while (1) {
        PSDP_NODE pId, pValue;

        pId = CONTAINING_RECORD(current, SDP_NODE, hdr.Link);
        current = current->Flink;
        pValue = CONTAINING_RECORD(current, SDP_NODE, hdr.Link);

        if (pId->u.uint16 == attribute) {
            return pValue;
        }

        current = current->Flink;

        if (current == &nodeList.Link) {
            //
            // end of the list, no match
            //
            return NULL;
        }
    }
}

STDMETHODIMP CSdpRecord::GetAttribute(USHORT attribute, NodeData *pData)
{
    if (pData == NULL) {
        return E_POINTER;
    }

    LOCK_LIST();

    if (nodeList.nodeCount < 2) {
        return E_FAIL;
    }

    PSDP_NODE pNode = GetAttributeValueNode(attribute);

    if (pNode) {
        CreateNodeDataFromSdpNode(pNode, pData);

⌨️ 快捷键说明

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