// interopsvcBObj.cpp : Implementation of CinteropsvcBObj

#include "stdafx.h"
#include "interopsvcBObj.h"

#include "..\wmsoapstruct\wmsoapstruct.h"
#include "..\wmsoapstruct\wmsoapstruct_i.c"

// CinteropsvcBObj

STDMETHODIMP CinteropsvcBObj::echoStructAsSimpleTypes(VARIANT inputStruct, BSTR *outputString, int *outputInteger, float *outputFloat)
{
	// get Iwmsoapstruct pointer
	IDispatch *pDispIn = inputStruct.pdispVal;
	Iwmsoapstruct *pIwmsoapstruct;
	HRESULT res = pDispIn->QueryInterface(IID_Iwmsoapstruct, (void **)&pIwmsoapstruct);
	if (FAILED(res))
	{
		return E_FAIL;
	}
    long lPos;
	VARIANT_BOOL bResult;
	VARIANT varContent;
	BSTR bstrMemberName;
	// iterate over members
    VariantInit(&varContent);
	for (pIwmsoapstruct->GetFirstMember(&bstrMemberName, &varContent, &lPos, &bResult);
			bResult == VARIANT_TRUE;
			pIwmsoapstruct->GetNextMember(&bstrMemberName, &varContent, &lPos, &bResult))
	{
        if (wcscmp(bstrMemberName, L"varString") == 0)
        {
            *outputString = SysAllocString(varContent.bstrVal);
        }
        else if (wcscmp(bstrMemberName, L"varFloat") == 0)
        {
            *outputFloat = varContent.fltVal;
        }
        else if (wcscmp(bstrMemberName, L"varInt") == 0)
        {
            *outputInteger = varContent.lVal;
        }
		SysFreeString(bstrMemberName);
		VariantClear(&varContent);
	}
	// release
	pIwmsoapstruct->Release();
	return S_OK;
}

STDMETHODIMP CinteropsvcBObj::echoSimpleTypesAsStruct(BSTR inputString, int inputInteger, float inputFloat, VARIANT *outputStruct)
{
	// instantiate struct object
	Iwmsoapstruct *pIwmsoapstruct;
	HRESULT res = CoCreateInstance( CLSID_wmsoapstruct,
									NULL, CLSCTX_SERVER,
									IID_Iwmsoapstruct,
									(void **) &pIwmsoapstruct);
	if (FAILED(res))
	{
		return E_FAIL;
	}
	// copy
	VARIANT_BOOL bResult;
	VARIANT varContent;
	// string member
	BSTR bstrMemberName = SysAllocString(L"varString");
	varContent.vt = VT_BSTR;
	varContent.bstrVal = SysAllocString(inputString);
	pIwmsoapstruct->SetMember(bstrMemberName, varContent, &bResult);
	SysFreeString(bstrMemberName);
	VariantClear(&varContent);
	// integer member
	bstrMemberName = SysAllocString(L"varInt");
	varContent.vt = VT_I4;
	varContent.lVal = inputInteger;
	pIwmsoapstruct->SetMember(bstrMemberName, varContent, &bResult);
	SysFreeString(bstrMemberName);
	VariantClear(&varContent);
	// float member
	bstrMemberName = SysAllocString(L"varFloat");
	varContent.vt = VT_R4;
	varContent.fltVal = inputFloat;
	pIwmsoapstruct->SetMember(bstrMemberName, varContent, &bResult);
	SysFreeString(bstrMemberName);
	VariantClear(&varContent);

		// now get IDispatch pointer
	IDispatch *pIDispatchOut;
	res = pIwmsoapstruct->QueryInterface(IID_IDispatch, (void **)&pIDispatchOut);
	if (FAILED(res))
	{
		pIwmsoapstruct->Release();
		return E_FAIL;
	}
	outputStruct->pdispVal = pIDispatchOut;
	outputStruct->vt |= VT_DISPATCH;
	// release
	pIwmsoapstruct->Release();
	return S_OK;
}

STDMETHODIMP CinteropsvcBObj::echo2DStringArray(VARIANT input2DStringArray, VARIANT *output2DStringArray)
{
	SafeArrayCopy(input2DStringArray.parray, &output2DStringArray->parray);
	output2DStringArray->vt |= (VT_ARRAY | VT_VARIANT); 
	return S_OK;
}

STDMETHODIMP CinteropsvcBObj::echoNestedStruct(VARIANT inputStruct, VARIANT *outputStruct)
{
	// now get Iwmsoapstruct pointer
	IDispatch *pDispIn = inputStruct.pdispVal;
	Iwmsoapstruct *pIwmsoapstructIn;
	HRESULT res = pDispIn->QueryInterface(IID_Iwmsoapstruct, (void **)&pIwmsoapstructIn);
	if (FAILED(res))
	{
		return E_FAIL;
	}
	// instantiate struct object
	Iwmsoapstruct *pIwmsoapstructOut;
	res = CoCreateInstance( CLSID_wmsoapstruct,
							NULL, CLSCTX_SERVER,
							IID_Iwmsoapstruct,
							(void **) &pIwmsoapstructOut);
	if (FAILED(res))
	{
		return E_FAIL;
	}
	// copy
	long lPos;
	VARIANT_BOOL bResult;
	VARIANT varContent;
	BSTR bstrMemberName;
	VariantInit(&varContent);
	for (pIwmsoapstructIn->GetFirstMember(&bstrMemberName, &varContent, &lPos, &bResult);
			bResult == VARIANT_TRUE;
			pIwmsoapstructIn->GetNextMember(&bstrMemberName, &varContent, &lPos, &bResult))
	{
		VARIANT_BOOL bSuccess;
		if (FAILED(pIwmsoapstructOut->SetMember(bstrMemberName, varContent, &bSuccess)) ||
                bSuccess == VARIANT_FALSE)
        {
		    SysFreeString(bstrMemberName);
		    VariantClear(&varContent);
    		pIwmsoapstructIn->Release();
    		pIwmsoapstructOut->Release();
		    return E_FAIL;
	    }
		SysFreeString(bstrMemberName);
		VariantClear(&varContent);
	}
	// now get IDispatch pointer
	IDispatch *pIDispatchOut;
	res = pIwmsoapstructOut->QueryInterface(IID_IDispatch, (void **)&pIDispatchOut);
	if (FAILED(res))
	{
		pIwmsoapstructIn->Release();
		pIwmsoapstructOut->Release();
		return E_FAIL;
	}
	outputStruct->pdispVal = pIDispatchOut;
	outputStruct->vt |= VT_DISPATCH;
	// release
	pIwmsoapstructIn->Release();
	pIwmsoapstructOut->Release();
	return S_OK;
}

STDMETHODIMP CinteropsvcBObj::echoNestedArray(VARIANT inputStruct, VARIANT *outputStruct)
{
	// now get Iwmsoapstruct pointer
	IDispatch *pDispIn = inputStruct.pdispVal;
	Iwmsoapstruct *pIwmsoapstructIn;
	HRESULT res = pDispIn->QueryInterface(IID_Iwmsoapstruct, (void **)&pIwmsoapstructIn);
	if (FAILED(res))
	{
		return E_FAIL;
	}
	// instantiate struct object
	Iwmsoapstruct *pIwmsoapstructOut;
	res = CoCreateInstance( CLSID_wmsoapstruct,
							NULL, CLSCTX_SERVER,
							IID_Iwmsoapstruct,
							(void **) &pIwmsoapstructOut);
	if (FAILED(res))
	{
		return E_FAIL;
	}
	// copy
	long lPos;
	VARIANT_BOOL bResult;
	VARIANT varContent;
	BSTR bstrMemberName;
	VariantInit(&varContent);
	for (pIwmsoapstructIn->GetFirstMember(&bstrMemberName, &varContent, &lPos, &bResult);
			bResult == VARIANT_TRUE;
			pIwmsoapstructIn->GetNextMember(&bstrMemberName, &varContent, &lPos, &bResult))
	{
		VARIANT_BOOL bSuccess;
		if (FAILED(pIwmsoapstructOut->SetMember(bstrMemberName, varContent, &bSuccess)) ||
                bSuccess == VARIANT_FALSE)
        {
		    SysFreeString(bstrMemberName);
		    VariantClear(&varContent);
    		pIwmsoapstructIn->Release();
    		pIwmsoapstructOut->Release();
		    return E_FAIL;
	    }
		SysFreeString(bstrMemberName);
		VariantClear(&varContent);
	}
	// now get IDispatch pointer
	IDispatch *pIDispatchOut;
	res = pIwmsoapstructOut->QueryInterface(IID_IDispatch, (void **)&pIDispatchOut);
	if (FAILED(res))
	{
		pIwmsoapstructIn->Release();
		pIwmsoapstructOut->Release();
		return E_FAIL;
	}
	outputStruct->pdispVal = pIDispatchOut;
	outputStruct->vt |= VT_DISPATCH;
	// release
	pIwmsoapstructIn->Release();
	pIwmsoapstructOut->Release();
	return S_OK;
}
