// <Include>
///////////////////////////////////////////////////////////////////////////////
//
// THIS FILE IS AUTOMATICALLY GENERATED.  DO NOT MODIFY IT BY HAND.
//
///////////////////////////////////////////////////////////////////////////////
// </Include>

// <LiteralInclude>
#include <wsdapi.h>
// </LiteralInclude>

// <LiteralInclude>
#include "SimpleThermostat_WSD.h"
// </LiteralInclude>

// <LiteralInclude>
#include "SimpleThermostat_WSDTypes.h"
// </LiteralInclude>

// <LiteralInclude>
#include "SimpleThermostat_WSDProxy.h"
// </LiteralInclude>

// <ProxyBuilderImplementations>
HRESULT CreateCSimpleThermostat_WSDProxy(
                LPCWSTR pszDeviceAddress,
                LPCWSTR pszLocalAddress,
                CSimpleThermostat_WSDProxy** ppProxyOut,
                IWSDXMLContext** ppContextOut)
{
    HRESULT hr = S_OK;
    IWSDXMLContext* pContext = NULL;
    IWSDDeviceProxy* pDeviceProxy = NULL;
    IWSDServiceProxy* pServiceProxy = NULL;
    CSimpleThermostat_WSDProxy* pProxy = NULL;

    // 
    // Validate parameters
    // 
    if( NULL == pszDeviceAddress )
    {
        return E_INVALIDARG;
    }

    if( NULL == pszLocalAddress )
    {
        return E_INVALIDARG;
    }

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

    // ppContextOut is optional

    *ppProxyOut = NULL;
    if( NULL != ppContextOut )
    {
        *ppContextOut = NULL;
    }

    // 
    // Create XML context for namespace and type registration
    // 
    hr = WSDXMLCreateContext(&pContext);

    // 
    // Register types used by the service
    // 
    if( S_OK == hr )
    {
        hr = SimpleThermostat_WSDRegisterTypes(pContext);
    }

    // 
    // Register namespaces used by the service
    // 
    if( S_OK == hr )
    {
        hr = SimpleThermostat_WSDRegisterNamespaces(pContext);
    }

    // 
    // Create a proxy for the device host
    // 
    if( S_OK == hr )
    {
        hr = WSDCreateDeviceProxy(pszDeviceAddress, pszLocalAddress, pContext, &pDeviceProxy);
    }

    // 
    // Create a proxy for the service
    // 
    if( S_OK == hr )
    {
        hr = pDeviceProxy->GetServiceProxyByType(&Names_Thermostat[0], &pServiceProxy);
    }

    // 
    // Create a proxy for the port type
    // 
    if( S_OK == hr )
    {
        pProxy = new CSimpleThermostat_WSDProxy();
        if( NULL == pProxy )
        {
            hr = E_OUTOFMEMORY;
        }
    }

    if( S_OK == hr )
    {
        hr = pProxy->Init(pServiceProxy);
    }

    // 
    // Cleanup
    // 
    if( NULL != pServiceProxy )
    {
        pServiceProxy->Release();
    }

    if( NULL != pDeviceProxy )
    {
        pDeviceProxy->Release();
    }

    if( S_OK == hr && ppContextOut )
    {
        *ppContextOut = pContext;
    }
    else
    {
        if( NULL != pContext )
        {
            pContext->Release();
        }
    }

    if( S_OK == hr )
    {
        *ppProxyOut = pProxy;
    }
    else
    {
        if( NULL != pProxy )
        {
            pProxy->Release();
        }
    }

    return hr;
}

// </ProxyBuilderImplementations>

// <CDATA>

CSimpleThermostat_WSDProxy::CSimpleThermostat_WSDProxy() :
    m_cRef(1), m_genericProxy(NULL)
{
}

CSimpleThermostat_WSDProxy::~CSimpleThermostat_WSDProxy() 
{
    if ( NULL != m_genericProxy )
    {
        m_genericProxy->Release();
        m_genericProxy = NULL;
    }
};

HRESULT STDMETHODCALLTYPE CSimpleThermostat_WSDProxy::Init(
    /* [in] */ IWSDServiceProxy* pIWSDServiceProxy )
{
    if( NULL == pIWSDServiceProxy )
    {
        return E_INVALIDARG;
    }

    m_genericProxy = pIWSDServiceProxy;
    m_genericProxy->AddRef();

    return S_OK;
}

// </CDATA>

// <IUnknownDefinitions>
HRESULT STDMETHODCALLTYPE CSimpleThermostat_WSDProxy::QueryInterface(REFIID riid, void **ppvObject)
{
    if (NULL == ppvObject)
    {
        return E_POINTER;
    }

    HRESULT hr = S_OK;
    *ppvObject = NULL;

    if (__uuidof(IUnknown) == riid)
    {
        *ppvObject = (IUnknown *)this;
    }
    else if (__uuidof(ISimpleThermostat_WSD) == riid)
    {
        *ppvObject = (ISimpleThermostat_WSD *)this;
    }
    else if (__uuidof(ISimpleThermostat_WSDProxy) == riid)
    {
        *ppvObject = (ISimpleThermostat_WSDProxy *)this;
    }
    else
    {
        hr = E_NOINTERFACE;
    }

    if (SUCCEEDED(hr))
    {
        ((LPUNKNOWN)*ppvObject)->AddRef();
    }

    return hr;
}

ULONG STDMETHODCALLTYPE CSimpleThermostat_WSDProxy::AddRef()
{
    ULONG ulNewRefCount = (ULONG)InterlockedIncrement((LONG *)&m_cRef);
    return ulNewRefCount;
}

ULONG STDMETHODCALLTYPE CSimpleThermostat_WSDProxy::Release()
{
    ULONG ulNewRefCount = (ULONG)InterlockedDecrement((LONG *)&m_cRef);

    if (0 == ulNewRefCount)
    {
        delete this;
    }

    return ulNewRefCount;
}
// </IUnknownDefinitions>

// <ProxyFunctionImplementations>
HRESULT STDMETHODCALLTYPE
CSimpleThermostat_WSDProxy::GetCurrentTemp
(   /* [out] */ LONG* tempOut
)
{
    HRESULT hr = S_OK;

    // Initialize Output Pointers
    if( NULL != tempOut )
    {
        *tempOut = NULL;
    }

    // Validate Response Parameters
    if( NULL == tempOut )
    {
        hr = E_POINTER;
        return hr;
    }

    if( NULL == m_genericProxy )
    {
        hr = E_ABORT;
        return hr;
    }

    IWSDEndpointProxy* ep = NULL;
    m_genericProxy->GetEndpointProxy(&ep);
    if( FAILED(hr) || NULL == ep )
    {
        hr = E_ABORT;
        return hr;
    }

    WSD_SYNCHRONOUS_RESPONSE_CONTEXT context;
    ::ZeroMemory(&context, sizeof(context));
    context.eventHandle = ::CreateEvent(NULL, FALSE, FALSE, NULL);
    if (NULL == context.eventHandle)
    {
        DWORD dw = ::GetLastError();
        hr = HRESULT_FROM_WIN32(dw);
        ep->Release();
        return hr;
    }
    hr = 
        ep->SendTwoWayRequest
        (   NULL
        ,   &Operations_SimpleThermostat_WSD[0]
        ,   &context
        );

    if (SUCCEEDED(hr))
    {
        if ( WAIT_FAILED == ::WaitForSingleObject(context.eventHandle, INFINITE) )
        {
             DWORD dw = ::GetLastError();
             hr = HRESULT_FROM_WIN32(dw);
        }
    }

    ::CloseHandle(context.eventHandle);
    context.eventHandle = NULL;

    if (SUCCEEDED(hr))
    {
        if (SUCCEEDED(context.hr))
        {
            if( NULL != context.results )
            {
                RESPONSEBODY_SimpleThermostat_WSD_GetCurrentTemp* response = reinterpret_cast<RESPONSEBODY_SimpleThermostat_WSD_GetCurrentTemp*>(context.results);

                *tempOut = response->temp;

                WSDFreeLinkedMemory( context.results );
                context.results = NULL;
            }
            else
            {
                hr = E_FAIL;
            }
        }
        else
        {
            hr = context.hr;
            if( context.results )
            {
                ep->ProcessFault( (const WSD_SOAP_FAULT*)context.results );
            }
        }
    }

    if ( NULL != context.messageParameters )
    {
        context.messageParameters->Release();
        context.messageParameters = NULL;
    }

    ep->Release();
    return hr;
}

HRESULT STDMETHODCALLTYPE
CSimpleThermostat_WSDProxy::GetDesiredTemp
(   /* [out] */ LONG* tempOut
)
{
    HRESULT hr = S_OK;

    // Initialize Output Pointers
    if( NULL != tempOut )
    {
        *tempOut = NULL;
    }

    // Validate Response Parameters
    if( NULL == tempOut )
    {
        hr = E_POINTER;
        return hr;
    }

    if( NULL == m_genericProxy )
    {
        hr = E_ABORT;
        return hr;
    }

    IWSDEndpointProxy* ep = NULL;
    m_genericProxy->GetEndpointProxy(&ep);
    if( FAILED(hr) || NULL == ep )
    {
        hr = E_ABORT;
        return hr;
    }

    WSD_SYNCHRONOUS_RESPONSE_CONTEXT context;
    ::ZeroMemory(&context, sizeof(context));
    context.eventHandle = ::CreateEvent(NULL, FALSE, FALSE, NULL);
    if (NULL == context.eventHandle)
    {
        DWORD dw = ::GetLastError();
        hr = HRESULT_FROM_WIN32(dw);
        ep->Release();
        return hr;
    }
    hr = 
        ep->SendTwoWayRequest
        (   NULL
        ,   &Operations_SimpleThermostat_WSD[1]
        ,   &context
        );

    if (SUCCEEDED(hr))
    {
        if ( WAIT_FAILED == ::WaitForSingleObject(context.eventHandle, INFINITE) )
        {
             DWORD dw = ::GetLastError();
             hr = HRESULT_FROM_WIN32(dw);
        }
    }

    ::CloseHandle(context.eventHandle);
    context.eventHandle = NULL;

    if (SUCCEEDED(hr))
    {
        if (SUCCEEDED(context.hr))
        {
            if( NULL != context.results )
            {
                RESPONSEBODY_SimpleThermostat_WSD_GetDesiredTemp* response = reinterpret_cast<RESPONSEBODY_SimpleThermostat_WSD_GetDesiredTemp*>(context.results);

                *tempOut = response->temp;

                WSDFreeLinkedMemory( context.results );
                context.results = NULL;
            }
            else
            {
                hr = E_FAIL;
            }
        }
        else
        {
            hr = context.hr;
            if( context.results )
            {
                ep->ProcessFault( (const WSD_SOAP_FAULT*)context.results );
            }
        }
    }

    if ( NULL != context.messageParameters )
    {
        context.messageParameters->Release();
        context.messageParameters = NULL;
    }

    ep->Release();
    return hr;
}

HRESULT STDMETHODCALLTYPE
CSimpleThermostat_WSDProxy::SetDesiredTemp
(   /* [in] */ LONG temp
)
{
    HRESULT hr = S_OK;

    REQUESTBODY_SimpleThermostat_WSD_SetDesiredTemp request;

    request.temp = temp;

    if( NULL == m_genericProxy )
    {
        hr = E_ABORT;
        return hr;
    }

    IWSDEndpointProxy* ep = NULL;
    m_genericProxy->GetEndpointProxy(&ep);
    if( FAILED(hr) || NULL == ep )
    {
        hr = E_ABORT;
        return hr;
    }

    hr = 
        ep->SendOneWayRequest
        (   &request
        ,   &Operations_SimpleThermostat_WSD[2]
        );

    ep->Release();
    return hr;
}

// </ProxyFunctionImplementations>

// <ProxyFunctionImplementations>
HRESULT STDMETHODCALLTYPE
CSimpleThermostat_WSDProxy::BeginGetCurrentTemp
(   /* [in] */ IUnknown* AsyncState
,   /* [in] */ IWSDAsyncCallback* AsyncCallback
,   /* [out] */ IWSDAsyncResult** AsyncResultOut
)
{
    HRESULT hr = S_OK;

    // Initialize Output Pointers
    if( NULL != AsyncResultOut )
    {
        *AsyncResultOut = NULL;
    }

    if( NULL == m_genericProxy )
    {
        hr = E_ABORT;
        return hr;
    }

    IWSDEndpointProxy* ep = NULL;
    m_genericProxy->GetEndpointProxy(&ep);
    if( FAILED(hr) || NULL == ep )
    {
        hr = E_ABORT;
        return hr;
    }

    hr = 
        ep->SendTwoWayRequestAsync
        (   NULL
        ,   &Operations_SimpleThermostat_WSD[0]
        ,   AsyncState
        ,   AsyncCallback
        ,   AsyncResultOut
        );

    ep->Release();
    return hr;
}

HRESULT STDMETHODCALLTYPE
CSimpleThermostat_WSDProxy::EndGetCurrentTemp
(   /* [in] */ IWSDAsyncResult* AsyncResult
,   /* [out] */ LONG* tempOut
)
{
    WSD_EVENT ev;
    HRESULT hr = S_OK;


    // Initialize Output Pointers
    if( NULL != tempOut )
    {
        *tempOut = NULL;
    }
    if( NULL == AsyncResult )
    {
        hr = E_INVALIDARG;
        return hr;
    }

    // Validate Response Parameters
    if( NULL == tempOut )
    {
        hr = E_POINTER;
        return hr;
    }

    ::ZeroMemory(&ev, sizeof(ev));
    hr = AsyncResult->GetEvent( &ev );
    if( S_OK != hr )
    {
        return hr;
    }

    if( ev.EventType == WSDET_INCOMING_MESSAGE )
    {
        void* results = ev.Soap->Body;
        if( NULL != results )
        {
            RESPONSEBODY_SimpleThermostat_WSD_GetCurrentTemp* response = reinterpret_cast<RESPONSEBODY_SimpleThermostat_WSD_GetCurrentTemp*>(results);

            *tempOut = response->temp;

            WSDFreeLinkedMemory( (void*) response );
        }
    }
    else if( ev.EventType == WSDET_INCOMING_FAULT )
    {
        void* results = ev.Soap->Body;

        if( NULL == m_genericProxy )
        {
            hr = E_ABORT;
            return hr;
        }

        IWSDEndpointProxy* ep = NULL;
        m_genericProxy->GetEndpointProxy(&ep);
        if( FAILED(hr) || NULL == ep )
        {
            hr = E_ABORT;
            return hr;
        }

        hr = E_FAIL;
        if( results )
        {
            ep->ProcessFault( (const WSD_SOAP_FAULT*)results );
        }
        ep->Release();
    }
    else
    {
        hr = ( (S_OK == ev.Hr) ? E_FAIL : ev.Hr );
    }

    return hr;
}

HRESULT STDMETHODCALLTYPE
CSimpleThermostat_WSDProxy::BeginGetDesiredTemp
(   /* [in] */ IUnknown* AsyncState
,   /* [in] */ IWSDAsyncCallback* AsyncCallback
,   /* [out] */ IWSDAsyncResult** AsyncResultOut
)
{
    HRESULT hr = S_OK;

    // Initialize Output Pointers
    if( NULL != AsyncResultOut )
    {
        *AsyncResultOut = NULL;
    }

    if( NULL == m_genericProxy )
    {
        hr = E_ABORT;
        return hr;
    }

    IWSDEndpointProxy* ep = NULL;
    m_genericProxy->GetEndpointProxy(&ep);
    if( FAILED(hr) || NULL == ep )
    {
        hr = E_ABORT;
        return hr;
    }

    hr = 
        ep->SendTwoWayRequestAsync
        (   NULL
        ,   &Operations_SimpleThermostat_WSD[1]
        ,   AsyncState
        ,   AsyncCallback
        ,   AsyncResultOut
        );

    ep->Release();
    return hr;
}

HRESULT STDMETHODCALLTYPE
CSimpleThermostat_WSDProxy::EndGetDesiredTemp
(   /* [in] */ IWSDAsyncResult* AsyncResult
,   /* [out] */ LONG* tempOut
)
{
    WSD_EVENT ev;
    HRESULT hr = S_OK;


    // Initialize Output Pointers
    if( NULL != tempOut )
    {
        *tempOut = NULL;
    }
    if( NULL == AsyncResult )
    {
        hr = E_INVALIDARG;
        return hr;
    }

    // Validate Response Parameters
    if( NULL == tempOut )
    {
        hr = E_POINTER;
        return hr;
    }

    ::ZeroMemory(&ev, sizeof(ev));
    hr = AsyncResult->GetEvent( &ev );
    if( S_OK != hr )
    {
        return hr;
    }

    if( ev.EventType == WSDET_INCOMING_MESSAGE )
    {
        void* results = ev.Soap->Body;
        if( NULL != results )
        {
            RESPONSEBODY_SimpleThermostat_WSD_GetDesiredTemp* response = reinterpret_cast<RESPONSEBODY_SimpleThermostat_WSD_GetDesiredTemp*>(results);

            *tempOut = response->temp;

            WSDFreeLinkedMemory( (void*) response );
        }
    }
    else if( ev.EventType == WSDET_INCOMING_FAULT )
    {
        void* results = ev.Soap->Body;

        if( NULL == m_genericProxy )
        {
            hr = E_ABORT;
            return hr;
        }

        IWSDEndpointProxy* ep = NULL;
        m_genericProxy->GetEndpointProxy(&ep);
        if( FAILED(hr) || NULL == ep )
        {
            hr = E_ABORT;
            return hr;
        }

        hr = E_FAIL;
        if( results )
        {
            ep->ProcessFault( (const WSD_SOAP_FAULT*)results );
        }
        ep->Release();
    }
    else
    {
        hr = ( (S_OK == ev.Hr) ? E_FAIL : ev.Hr );
    }

    return hr;
}

// </ProxyFunctionImplementations>

