// AsynCallDemo.cpp : CAsynCallDemo 的实现

#include "stdafx.h"
#include "AsynCallDemo.h"
#include ".\asyncalldemo.h"

#include "comdef.h"


// CAsynCallDemo

/*  此函数应该同windows函数 CoMarshalInterThreadInterfaceInStream
    的内部实现差不多,只是里面调用的参数可能有细微差别 */
static HRESULT
myCoMarshalInterThreadInterfaceInStream(
                    REFIID riid,
                    LPUNKNOWN pUnk,
                    LPSTREAM * ppStm)
{
    HRESULT		hres;

    hres = CreateStreamOnHGlobal(NULL, TRUE, ppStm);
    if (FAILED(hres)) return hres;
    hres = CoMarshalInterface(*ppStm, riid, pUnk, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLESTRONG);

    if (FAILED(hres))
    {
        (*ppStm)->Release();
        *ppStm = NULL;
    }

    return hres;
}

STDMETHODIMP CAsynCallDemo::SetDemoFunc(IDispatch* jsFunc)
{
    // TODO: 在此添加实现代码
    IDispatch *tmp;
    if(m_pStream)
    {
        CoReleaseMarshalData(m_pStream);
        m_pStream->Release();
        m_pStream = NULL;
    }
    if(m_cbmethod)
    {
        tmp = m_cbmethod;
        m_cbmethod = NULL;
        tmp->Release();
    }

    tmp = jsFunc;
    if(tmp==NULL)
        return S_OK;
    tmp->AddRef();
    m_cbmethod = tmp;
    if(FAILED(myCoMarshalInterThreadInterfaceInStream(IID_IDispatch,m_cbmethod,&m_pStream)))
    {
        //发生错误
        m_cbmethod->Release();
        m_cbmethod = NULL;
        return S_FALSE;
    }

    m_dlg.StartDialog();

    return S_OK;
}
void CAsynCallDemo::do_call(void)
{
    WCHAR argstr[64];
    SYSTEMTIME ctm;

    ULARGE_INTEGER	    xpos;
    LARGE_INTEGER		seekto;

    IDispatch *pDisp;
    HRESULT hr;

    if(m_pStream==NULL)
        return;

    memset(&seekto,0,sizeof(seekto));
    /* 不判断错误了 */
    m_pStream->Seek(seekto,STREAM_SEEK_SET,&xpos);

    hr = CoUnmarshalInterface(m_pStream,IID_IDispatch,(void**)&pDisp);
    if(FAILED(hr))
    {
        MessageBoxA(m_dlg.m_hWnd,"Error!",0,MB_ICONERROR);
        return;
    }

    GetLocalTime(&ctm);
    swprintf(argstr,L"当前时间是:%02d-%02d-%02d.%03d",
                ctm.wHour,ctm.wMinute,ctm.wSecond,ctm.wMilliseconds);

    _com_dispatch_raw_method(pDisp,0,DISPATCH_METHOD,VT_EMPTY,NULL,
        L"\x0008",::SysAllocString(argstr));
    pDisp->Release();
}
