📄 sdprecord.cpp
字号:
if (pNode->hdr.Type == SDP_TYPE_URL) {
CopyStringDataToNodeData(pNode->u.url,
pNode->DataSize,
&pData->u.url);
}
else if (pNode->hdr.Type == SDP_TYPE_STRING) {
CopyStringDataToNodeData(pNode->u.string,
pNode->DataSize,
&pData->u.str);
}
return S_OK;
}
else {
return E_FAIL;
}
}
STDMETHODIMP CSdpRecord::GetAttributeAsStream(USHORT attribute, UCHAR **ppStream, ULONG *pSize)
{
if (ppStream == NULL || pSize == NULL) {
return E_POINTER;
}
LOCK_LIST();
PSDP_NODE pNode = GetAttributeValueNode(attribute);
if (pNode) {
if (pNode->hdr.Type == SDP_TYPE_CONTAINER) {
return pNode->u.container->CreateStream(ppStream, pSize);
}
else {
//
// save the links in the list to be restored later
//
LIST_ENTRY e = pNode->hdr.Link;
//
// ComputeNodeListSize will iterate over the entire list, so we want to
// single this node out for the call
//
SDP_NODE listHead;
SdpInitializeNodeHeader(&listHead.hdr);
Sdp_InsertTailList(&listHead.hdr.Link,&pNode->hdr.Link);
ULONG size = 0;
ComputeNodeListSize(pNode, &size);
//
// OK, we are done, restore the links back again
//
pNode->hdr.Link = e;
PUCHAR stream = (PUCHAR) CoTaskMemAlloc(size);
if (stream == NULL) {
return E_OUTOFMEMORY;
}
ZeroMemory(stream, size);
WriteLeafToStream(pNode, stream);
*pSize = size;
*ppStream = stream;
return S_OK;
}
}
else {
return E_FAIL;
}
}
STDMETHODIMP CSdpRecord::Walk(ISdpWalk *pWalk)
{
HRESULT err;
// NodeData ndc;
if (pWalk == NULL) {
return E_POINTER;
}
LockRecord(TRUE);
err = nodeList.Walk(pWalk);
LockRecord(FALSE);
return err;
}
STDMETHODIMP CSdpRecord::GetAttributeList(USHORT **ppList, ULONG *pListSize)
{
if (ppList == NULL || pListSize == NULL) {
return E_POINTER;
}
LOCK_LIST();
ULONG size = nodeList.nodeCount / 2;
USHORT *list;
list = (PUSHORT) CoTaskMemAlloc(size * sizeof(USHORT));
if (list == NULL) {
ZeroMemory(list, size * sizeof(USHORT));
*ppList = NULL;
*pListSize = 0;
return E_OUTOFMEMORY;
}
*ppList = list;
*pListSize = size;
PLIST_ENTRY entry = nodeList.Link.Flink;
for (ULONG c = 0; c < size; c++, entry = entry->Flink->Flink, list++) {
PSDP_NODE pNode = CONTAINING_RECORD(entry, SDP_NODE, hdr.Link);
*list = pNode->u.uint16;
}
return S_OK;
}
HRESULT CSdpRecord::GetLangBaseInfo(USHORT *pLangId, USHORT *pMibeNum, USHORT *pAttribId)
{
#if (defined (UNDER_CE) || defined (WINCE_EMULATION))
return E_NOTIMPL;
#else
PSDP_NODE pNode;
//
// Iterate over the languages supported by this record and see if we
// find a match
//
pNode = GetAttributeValueNode(SDP_ATTRIB_LANG_BASE_ATTRIB_ID_LIST);
if (pNode && pNode->hdr.Type == SDP_TYPE_CONTAINER) {
ISdpNodeContainer *pCont = pNode->u.container;
ULONG count, i;
pCont->GetNodeCount(&count);
if ((count % 3) != 0) {
//
// malformed data
//
return E_FAIL;
}
//
// The language ID list has the following format
// SEQ
// UINT16 language
// UINT16 character encoding
// UINT16 starting attribute
// ... triplets etc ...
//
for (i = 0; i < count; /* i incremented in the loop */ ) {
NodeData nd;
USHORT langId, mibeNum, id;
//
// get the language id
//
pCont->GetNode(i++, &nd);
if (nd.type != SDP_TYPE_UINT || nd.specificType != SDP_ST_UINT16 ) {
return E_INVALIDARG;
}
langId = nd.u.uint16;
//
// grab the encoding scheme
//
pCont->GetNode(i++, &nd);
if (nd.type != SDP_TYPE_UINT || nd.specificType != SDP_ST_UINT16 ) {
return E_INVALIDARG;
}
mibeNum = nd.u.uint16;
//
// grab the attribute where this string starts
//
pCont->GetNode(i++, &nd);
if (nd.type != SDP_TYPE_UINT || nd.specificType != SDP_ST_UINT16 ) {
return E_INVALIDARG;
}
id = nd.u.uint16;
//
// If pLangid is NULL, then the caller wants the default string.
// The default string is always the first one
//
if (pLangId == NULL || *pLangId == langId) {
*pMibeNum = mibeNum;
*pAttribId = id;
return S_OK;
}
}
}
return E_FAIL;
#endif // UNDER_CE
}
STDMETHODIMP CSdpRecord::GetString(USHORT offset, USHORT *pLangId, WCHAR **ppString)
{
#if (defined (UNDER_CE) || defined (WINCE_EMULATION))
return E_NOTIMPL;
#else
PSDP_NODE pNode;
HRESULT hres = S_OK;
USHORT id, mibeNum, langId;
if (ppString == NULL) {
return E_INVALIDARG;
}
*ppString = NULL;
LOCK_LIST();
hres = GetLangBaseInfo(pLangId, &mibeNum, &id);
if (!SUCCEEDED(hres) && pLangId == NULL) {
//
// Assume the defaults since the record itself does not contain any
// language base information
//
mibeNum = 106; // utf 8
id = LANG_DEFAULT_ID; // 0x100
hres = S_OK;
}
if (SUCCEEDED(hres)) {
pNode = GetAttributeValueNode(id + offset);
WCHAR *pszCharset = FindCharset(mibeNum);
if (pNode && pNode->hdr.Type == SDP_TYPE_STRING && pszCharset != NULL) {
IMultiLanguage2 * pMLang;
hres = CoCreateInstance(CLSID_CMultiLanguage,
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IMultiLanguage2),
(PVOID *) &pMLang);
if (SUCCEEDED(hres)) {
MIMECSETINFO mime = { 0 };
hres = pMLang->GetCharsetInfo(pszCharset, &mime);
if (SUCCEEDED(hres)) {
DWORD dwMode = 0;
UINT inSize = pNode->DataSize, outSize = 0;
BOOLEAN appendNull = FALSE;
//
// The string in the record does not have to be null
// terminated. If it isn't, we must compensate for this
// later on when we allocate memory and after the conversion
//
if (pNode->u.string[inSize-1] != NULL) {
appendNull = TRUE;
}
//
// Get the size required
//
hres = pMLang->ConvertStringToUnicode(&dwMode,
mime.uiInternetEncoding,
pNode->u.string,
&inSize,
NULL,
&outSize);
if (SUCCEEDED(hres)) {
if (appendNull) {
// allocate an extra character
outSize++;
}
*ppString = (WCHAR*) CoTaskMemAlloc(outSize * sizeof(WCHAR));
if (*ppString) {
//
// finally, convert the string
//
hres = pMLang->
ConvertStringToUnicode(&dwMode,
mime.uiInternetEncoding,
pNode->u.string,
&inSize,
*ppString,
&outSize);
if (SUCCEEDED(hres)) {
if (appendNull) {
//
// Need to append a null, outSize contains
// the number of chars written, and since
// the size of the buffer is outSize+1, we
// can safely use outSize as an index
//
(*ppString)[outSize] = 0;
}
}
else {
CoTaskMemFree(*ppString);
*ppString = NULL;
}
}
else {
hres = E_OUTOFMEMORY;
}
}
}
pMLang->Release();
}
}
else {
hres = E_FAIL;
}
}
return hres;
#endif // UNDER_CE
}
#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
struct ClassToID {
const GUID *sc;
WORD id;
} g_ClassIconMapping[] = {
{ &SerialPortServiceClass_UUID, IDI_SERIAL },
{ &GenericNetworkingServiceClass_UUID, IDI_NET },
{ &FaxServiceClass_UUID, IDI_DUN },
{ &DialupNetworkingServiceClass_UUID, IDI_DUN },
{ &GenericAudioServiceClass_UUID, IDI_SPEAKER },
{ &HeadsetServiceClass_UUID, IDI_SPEAKER },
{ &OBEXFileTransferServiceClass_UUID, IDI_OBEX },
{ &OBEXObjectPushServiceClass_UUID, IDI_OBEX },
};
#endif // UNDER_CE
STDMETHODIMP CSdpRecord::GetIcon(int cxRes, int cyRes, HICON *phIcon)
{
#if (defined (UNDER_CE) || defined (WINCE_EMULATION))
return E_NOTIMPL;
#else
GUID sc;
HRESULT hres = GetServiceClass(&sc);
if (SUCCEEDED(hres)) {
hres = E_FAIL;
for (ULONG i = 0; i < ARRAY_SIZE(g_ClassIconMapping); i++) {
if (*g_ClassIconMapping[i].sc == sc) {
*phIcon = (HICON)
LoadImage(_Module.GetModuleInstance(),
MAKEINTRESOURCE(g_ClassIconMapping[i].id),
IMAGE_ICON,
cxRes,
cyRes,
0);
if (*phIcon != NULL) {
hres = S_OK;
}
break;
}
}
}
if (!SUCCEEDED(hres)) {
// load default icon by default
*phIcon = (HICON)
LoadImage(_Module.GetModuleInstance(),
MAKEINTRESOURCE(IDI_DEFAULT_MAJOR_CLASS),
IMAGE_ICON,
cxRes,
cyRes,
0);
hres = S_OK;
}
if (SUCCEEDED(hres) && *phIcon == NULL) {
return E_FAIL;
}
return hres;
#endif // UNDER_CE
}
STDMETHODIMP CSdpRecord::GetServiceClass(LPGUID pServiceClass)
{
HRESULT hres;
if (pServiceClass == NULL) {
return E_INVALIDARG;
}
NodeData nd;
hres = GetAttribute(SDP_ATTRIB_CLASS_ID_LIST, &nd);
if (SUCCEEDED(hres)) {
if (nd.type == SDP_TYPE_CONTAINER) {
NodeData ndUuid;
hres = nd.u.container->GetNode(0, &ndUuid);
if (SUCCEEDED(hres)) {
return pNormalizeUuid(&ndUuid, pServiceClass);
}
}
else {
hres = E_FAIL;
}
}
return hres;
}
STDMETHODIMP CSdpRecord::GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium)
{
return E_NOTIMPL;
}
STDMETHODIMP CSdpRecord::GetDataHere(FORMATETC *pformatetc, STGMEDIUM *pmedium)
{
return E_NOTIMPL;
}
STDMETHODIMP CSdpRecord::QueryGetData(FORMATETC *pformatetc)
{
return E_NOTIMPL;
}
STDMETHODIMP CSdpRecord::GetCanonicalFormatEtc(FORMATETC *pformatectIn, FORMATETC *pformatetcOut)
{
return E_NOTIMPL;
}
STDMETHODIMP CSdpRecord::SetData(FORMATETC *pformatetc, STGMEDIUM *pmedium, BOOL fRelease)
{
return E_NOTIMPL;
}
STDMETHODIMP CSdpRecord::EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc)
{
return E_NOTIMPL;
}
STDMETHODIMP CSdpRecord::DAdvise(FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection)
{
return E_NOTIMPL;
}
STDMETHODIMP CSdpRecord::DUnadvise(DWORD dwConnection)
{
return E_NOTIMPL;
}
STDMETHODIMP CSdpRecord::EnumDAdvise(IEnumSTATDATA **ppenumAdvise)
{
return E_NOTIMPL;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -