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

📄 automationproxy.cpp

📁 Windows CE 6.0 Server 源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
//+---------------------------------------------------------------------------
//
//  Microsoft Windows
//
//  File:       A U T O M A T I O N P R O X Y . C P P
//
//  Contents:   Implementation of the Automation Proxy class
//
//  Notes:
//
//  Author:     spather   2000/09/25
//
//----------------------------------------------------------------------------

#include <windows.h>
#include <upnpdevapi.h>
#include <ncbase.h>
#include <ncdebug.h>
#include "trace.h"

#include "upnphost.h"
#include "AutomationProxy.h"
#include "DataType.hxx"
#include "variant.h"

#include "host_i.c"

/*
 * Enum SST_DATA_TYPE
 *
 * Possible types of state variables
 */

enum SST_DATA_TYPE
{                               // ----------------------
    SDT_STRING = 0,             // VT_BSTR
    SDT_NUMBER,                 // VT_BSTR
    SDT_INT,                    // VT_I4
    SDT_FIXED_14_4,             // VT_CY
    SDT_BOOLEAN,                // VT_BOOL
    SDT_DATETIME_ISO8601,       // VT_DATE
    SDT_DATETIME_ISO8601TZ,     // VT_DATE
    SDT_DATE_ISO8601,           // VT_DATE
    SDT_TIME_ISO8601,           // VT_DATE
    SDT_TIME_ISO8601TZ,         // VT_DATE
    SDT_I1,                     // VT_I1
    SDT_I2,                     // VT_I2
    SDT_I4,                     // VT_I4
    SDT_UI1,                    // VT_UI1
    SDT_UI2,                    // VT_UI2
    SDT_UI4,                    // VT_UI4
    SDT_R4,                     // VT_FLOAT
    SDT_R8,                     // VT_DOUBLE
    SDT_FLOAT,                  // VT_DOUBLE
    SDT_UUID,                   // VT_BSTR
    SDT_BIN_BASE64,             // VT_ARRAY
    SDT_BIN_HEX,                // VT_ARRAY
    SDT_CHAR,                   // VT_UI2 (a wchar)
    SDT_URI,                    // VT_BSTR
    //
    // note(cmr): ADD NEW VALUES IMMEDIATELY BEFORE THIS COMMENT
    //
    SDT_INVALID
};


struct DTNAME
{
    LPCWSTR         m_pszType;
    SST_DATA_TYPE   m_sdt;
};


// Lookup table, sorted by string
// Note: if you add strings here, you also have to add a
//       corresponding entry to SST_DATA_TYPE
//
static CONST DTNAME g_rgdtTypeStrings[] =
{
    {L"bin.base64",     SDT_BIN_BASE64},        // base64 as defined in the MIME IETF spec
    {L"bin.hex",        SDT_BIN_HEX},           // Hexadecimal digits representing octets VT_ARRAY safearray or stream 
    {L"boolean",        SDT_BOOLEAN},           // boolean, "1" or "0" VT_BOOL int 
    {L"char",           SDT_CHAR},              // char, string VT_UI2 wchar 
    {L"date",           SDT_DATE_ISO8601},      // date.iso8601, A date in ISO 8601 format. (no time) VT_DATE long 
    {L"dateTime",       SDT_DATETIME_ISO8601},  // dateTime.iso8601, A date in ISO 8601 format, with optional time and no optional zone. Fractional seconds may be as precise as nanoseconds. VT_DATE long 
    {L"dateTime.tz",    SDT_DATETIME_ISO8601TZ},// dateTime.iso8601tz, A date in ISO 8601 format, with optional time and optional zone. Fractional seconds may be as precise as nanoseconds. VT_DATE long 
    {L"fixed.14.4",     SDT_FIXED_14_4},        // fixed.14.4, Same as "number" but no more than 14 digits to the left of the decimal point, and no more than 4 to the right. VT_CY large_integer 
    {L"float",          SDT_FLOAT},             // float, Same as for "number." VT_R8 double 
    {L"i1",             SDT_I1},                // i1, A number, with optional sign, no fractions, no exponent. VT_I1 char 
    {L"i2",             SDT_I2},                // i2, " VT_I2 short 
    {L"i4",             SDT_I4},                // i4, " VT_I4 long
    {L"int",            SDT_INT},               // int, A number, with optional sign, no fractions, no exponent. VT_I4 long 
    {L"number",         SDT_NUMBER},            // number, A number, with no limit on digits, may potentially have a leading sign, fractional digits, and optionally an exponent. Punctuation as in US English. VT_R8 double 
    {L"r4",             SDT_R4},                // r4, Same as "number." VT_FLOAT float 
    {L"r8",             SDT_R8},                // r8, " VT_DOUBLE double 
    {L"string",         SDT_STRING},            // string, pcdata VT_BSTR BSTR 
    {L"time",           SDT_TIME_ISO8601},      // time.iso8601, A time in ISO 8601 format, with no date and no time zone. VT_DATE long 
    {L"time.tz",        SDT_TIME_ISO8601TZ},    // time.iso8601.tz, A time in ISO 8601 format, with no date but optional time zone. VT_DATE. long 
    {L"ui1",            SDT_UI1},               // ui1, A number, unsigned, no fractions, no exponent. VT_UI1 unsigned char 
    {L"ui2",            SDT_UI2},               // ui2, " VT_UI2 unsigned short 
    {L"ui4",            SDT_UI4},               // ui4, " VT_UI4 unsigned long
    {L"uri",            SDT_URI},               // uri, Universal Resource Identifier VT_BSTR BSTR 
    {L"uuid",           SDT_UUID},              // uuid, Hexadecimal digits representing octets, optional embedded hyphens which should be ignored. VT_BSTR GUID 
    //
    // note(cmr): ADD NEW VALUES IN ALPHABETICAL ORDER
    //
};

// NOTE: the order of elements in this array must correspond to the order of 
// elements in the SST_DATA_TYPE enum.
static CONST VARTYPE g_rgvtTypes[] =
{                               
    VT_BSTR,
    VT_BSTR,
    VT_I4,
    VT_CY,
    VT_BOOL,
    VT_DATE,
    VT_DATE,
    VT_DATE,
    VT_DATE,
    VT_DATE,
    VT_I1,
    VT_I2,
    VT_I4,
    VT_UI1,
    VT_UI2,
    VT_UI4,
    VT_R4,
    VT_R8,
    VT_R8,
    VT_BSTR,
    VT_ARRAY | VT_UI1,
    VT_ARRAY | VT_UI1,
    VT_UI2,
    VT_BSTR,
    //
    // note(cmr): ADD NEW VALUES IMMEDIATELY BEFORE THIS COMMENT. 
    //            If adding new values, see comment above.
    //
    VT_EMPTY
};


PWSTR           COMSzFromWsz(PCWSTR pszSource);
SST_DATA_TYPE   GetTypeFromString(LPCWSTR pszTypeString);
VARTYPE         GetVarTypeFromString(LPCWSTR pszTypeString);



////////////////////////////////////////////////////////////////////////////
// CUPnPAutomationProxy
CUPnPAutomationProxy::CUPnPAutomationProxy()
    : m_rgVariables(m_StateVars),
      m_rgActions(m_Actions),
      m_fInitialized(FALSE),
      m_pdispService(NULL),
      m_cVariables(0),
      m_cActions(0),
      m_strType(NULL),
      m_bRetval(false),
      m_bSendEvents(false),
      m_pCurrentAction(NULL)
{
}


CUPnPAutomationProxy::~CUPnPAutomationProxy()
{
    if (m_pdispService)
        m_pdispService->Release();
}


STDMETHODIMP
CUPnPAutomationProxy::Initialize(
    /*[in]*/   IUnknown    * punkSvcObject,
    /*[in]*/   LPWSTR      pszSvcDescription)
{
    HRESULT hr = S_OK;

    Assert(!m_fInitialized);

    hr = punkSvcObject->QueryInterface(IID_IDispatch,
                                       (void **) &m_pdispService);

    if (SUCCEEDED(hr))
    {
        TraceTag(ttidAutomationProxy,
                 "CUPnPAutomationProxy::Initialize(): "
                 "Successfully obtained IDispatch pointer on service");

        hr = Parse(pszSvcDescription);
    }

    if (SUCCEEDED(hr))
    {
        m_fInitialized = TRUE;
    }

    TraceError("CUPnPAutomationProxy::Initialize(): "
               "Exiting",
               hr);
    return hr;
}


STDMETHODIMP
CUPnPAutomationProxy::QueryStateVariablesByDispIds(
    /*[in]*/   DWORD       cDispIds,
    /*[in]*/   DISPID      * rgDispIds,
    /*[out]*/  DWORD       * pcVariables,
    /*[out]*/  LPWSTR      ** prgszVariableNames,
    /*[out]*/  VARIANT     ** prgvarVariableValues,
    /*[out]*/  LPWSTR      ** prgszVariableDataTypes)
{
    HRESULT hr = S_OK;
    DWORD   cDispIdsToLookUp;
    DISPID  * rgDispIdsToLookUp;
    DISPID  * rgDispIdsToLookUpMem = NULL;
    LPWSTR  * rgszVariableNames = NULL;
    VARIANT * rgvarVariableValues = NULL;
    LPWSTR  * rgszVariableDataTypes = NULL;
    DWORD   cVariables = 0;

    Assert(m_fInitialized);

    if (0 == cDispIds)
    {
        // This means return all variables. Make an array of all our dispids.
        cDispIdsToLookUp = 0;
        rgDispIdsToLookUp = rgDispIdsToLookUpMem = new DISPID[m_cVariables];

        if (rgDispIdsToLookUp)
        {
            for (DWORD i = 0; i < m_cVariables; i++)
            {
                if(m_rgVariables[i].bEvented)
                    rgDispIdsToLookUp[cDispIdsToLookUp++] = m_rgVariables[i].dispid;
            }
        }
        else
        {
            hr = E_OUTOFMEMORY;
            TraceError("CUPnPAutomationProxy::"
                       "QueryStateVariablesByDispIds(): "
                       "Could not allocate array of dispids",
                       hr);
        }
    }
    else
    {
        cDispIdsToLookUp = cDispIds;
        rgDispIdsToLookUp = rgDispIds;
    }

    if (SUCCEEDED(hr))
    {
        // Allocate output arrays of size cDispIds.

        rgszVariableNames = (LPWSTR *)CoTaskMemAlloc(
            cDispIdsToLookUp * sizeof(LPWSTR));
        rgvarVariableValues = (VARIANT *)CoTaskMemAlloc(
            cDispIdsToLookUp * sizeof(VARIANT));
        rgszVariableDataTypes = (LPWSTR *)CoTaskMemAlloc(
            cDispIdsToLookUp * sizeof(LPWSTR));

        // Fill in values.

        if (rgszVariableNames && rgvarVariableValues && rgszVariableDataTypes)
        {
            ZeroMemory(rgszVariableNames, cDispIdsToLookUp * sizeof(LPWSTR));
            ZeroMemory(rgvarVariableValues, cDispIdsToLookUp * sizeof(VARIANT));
            ZeroMemory(rgszVariableDataTypes, cDispIdsToLookUp * sizeof(LPWSTR));

            for (DWORD i = 0; SUCCEEDED(hr) && (i < cDispIdsToLookUp); i++)
            {
                UPNP_STATE_VARIABLE    * pVariable = NULL;

                cVariables++;

                pVariable = LookupVariableByDispID(rgDispIdsToLookUp[i]);

                if (pVariable)
                {
                    rgszVariableNames[i] = COMSzFromWsz(pVariable->strName);
                    rgszVariableDataTypes[i] = COMSzFromWsz(pVariable->strDataType);

                    if (rgszVariableNames[i] && rgszVariableDataTypes[i])
                    {
                        UINT uArgErr = 0;
                        DISPPARAMS dispparamsEmpty = {NULL, NULL, 0, 0};

                        hr = m_pdispService->Invoke(rgDispIdsToLookUp[i],
                                                    IID_NULL,
                                                    LOCALE_SYSTEM_DEFAULT,
                                                    DISPATCH_PROPERTYGET,
                                                    &dispparamsEmpty,
                                                    &rgvarVariableValues[i],
                                                    NULL,
                                                    &uArgErr);
                        if (SUCCEEDED(hr))
                        {
                            hr = StringizeVariant(&rgvarVariableValues[i], pVariable->strDataType);
                        }

                        if (SUCCEEDED(hr))
                        {
                            TraceTag(ttidAutomationProxy,
                                     "CUPnPAutomationProxy::"
                                     "QueryStateVariablesByDispIds(): "
                                     "Successfully obtained value %S for "
                                     "dispid %d",
                                     V_BSTR(&rgvarVariableValues[i]),
                                     rgDispIdsToLookUp[i]);
                        }
                        else
                        {
                            TraceError("CUPnPAutomationProxy::"
                                       "QueryStateVariablesByDispIds(): "
                                       "IDispatch::Invoke failed",
                                       hr);
                        }
                    }
                    else
                    {
                        hr = E_OUTOFMEMORY;
                        TraceError("CUPnPAutomationProxy::"
                                   "QueryStateVariablesByDispIds(): "
                                   "Could not allocate name/data type strings",
                                   hr);
                    }
                }
                else
                {
                    hr = DISP_E_MEMBERNOTFOUND;
                }
            }
        }
        else
        {
            hr = E_OUTOFMEMORY;
            TraceError("CUPnPAutomationProxy::"
                       "QueryStateVariablesByDispIds(): "
                       "Could not allocate output arrays",
                       hr);
        }
    }


    // Copy the output arrays to the out parameters.
    if (SUCCEEDED(hr))
    {
        *pcVariables = cVariables;
        *prgszVariableNames = rgszVariableNames;
        *prgvarVariableValues = rgvarVariableValues;
        *prgszVariableDataTypes = rgszVariableDataTypes;
    }
    else
    {
        // Clean up. Assume cVariables accurately describes the number
        // of initialized items in the arrays.

        if (rgszVariableNames)
        {
            for (DWORD i = 0; i < cVariables; i++)
            {
                if (rgszVariableNames[i])
                {
                    CoTaskMemFree(rgszVariableNames[i]);
                    rgszVariableNames[i] = NULL;

⌨️ 快捷键说明

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