// soap12testsvcrpcObj.cpp : Implementation of Csoap12testsvcrpcObj

#include "stdafx.h"
#include "soap12testsvcrpcObj.h"

#include "..\wmsoapstruct\wmsoapstruct.h"
#include "..\wmsoapstruct\wmsoapstruct_i.c"
#include <stdio.h>
#include <time.h>

// Csoap12testsvcrpcObj

STDMETHODIMP Csoap12testsvcrpcObj::returnVoid()
{
	// does nothing

	return S_OK;
}

STDMETHODIMP Csoap12testsvcrpcObj::echoVoid()
{
	// does nothing

	return S_OK;
}

STDMETHODIMP Csoap12testsvcrpcObj::echoStruct(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, bstrMemberNS;
	
    VariantInit(&varContent);
	for (pIwmsoapstructIn->GetFirstMemberQN(&bstrMemberName, &bstrMemberNS, &varContent, &lPos, &bResult);
			bResult == VARIANT_TRUE;
			pIwmsoapstructIn->GetNextMemberQN(&bstrMemberName, &bstrMemberNS, &varContent, &lPos, &bResult))
	{
		VARIANT_BOOL bSuccess;
		if (FAILED(pIwmsoapstructOut->SetMemberQN(bstrMemberName, bstrMemberNS, varContent, &bSuccess)) ||
                bSuccess == VARIANT_FALSE)
        {
		    SysFreeString(bstrMemberName);
		    SysFreeString(bstrMemberNS);
		    VariantClear(&varContent);
    		pIwmsoapstructIn->Release();
    		pIwmsoapstructOut->Release();
		    return E_FAIL;
	    }
		SysFreeString(bstrMemberName);
		SysFreeString(bstrMemberNS);
		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 Csoap12testsvcrpcObj::echoStructArray(VARIANT inputStructArray, VARIANT *outputStructArray)
{
	SafeArrayCopy(inputStructArray.parray, &outputStructArray->parray);
	outputStructArray->vt |= (VT_VARIANT | VT_ARRAY);

	return S_OK;
}

STDMETHODIMP Csoap12testsvcrpcObj::echoStructAsSimpleTypes(VARIANT inputStruct, BSTR *outputString, int *outputInteger, float *outputFloat)
{
	// now get Iwmsoapstruct pointer
	IDispatch *pDispIn = inputStruct.pdispVal;
	Iwmsoapstruct *pIwmsoapstruct;
	HRESULT res = pDispIn->QueryInterface(IID_Iwmsoapstruct, (void **)&pIwmsoapstruct);
	if (FAILED(res))
	{
		return E_FAIL;
	}
    // get struct member data
    long lPos;
	VARIANT_BOOL bResult;
	VARIANT varContent;
	BSTR bstrMemberName;
	
    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 Csoap12testsvcrpcObj::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 Csoap12testsvcrpcObj::echo2DStringArray(VARIANT input2DStringArray, VARIANT *output2DStringArray)
{
	SafeArrayCopy(input2DStringArray.parray, &output2DStringArray->parray);
	output2DStringArray->vt |= (VT_ARRAY | VT_VARIANT); 
	return S_OK;
}

STDMETHODIMP Csoap12testsvcrpcObj::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, bstrMemberNS;
	VariantInit(&varContent);
	for (pIwmsoapstructIn->GetFirstMemberQN(&bstrMemberName, &bstrMemberNS, &varContent, &lPos, &bResult);
			bResult == VARIANT_TRUE;
			pIwmsoapstructIn->GetNextMemberQN(&bstrMemberName, &bstrMemberNS, &varContent, &lPos, &bResult))
	{
		VARIANT_BOOL bSuccess;
		if (FAILED(pIwmsoapstructOut->SetMemberQN(bstrMemberName, bstrMemberNS, varContent, &bSuccess)) ||
                bSuccess == VARIANT_FALSE)
        {
		    SysFreeString(bstrMemberName);
		    SysFreeString(bstrMemberNS);
		    VariantClear(&varContent);
    		pIwmsoapstructIn->Release();
    		pIwmsoapstructOut->Release();
		    return E_FAIL;
	    }
		SysFreeString(bstrMemberName);
		SysFreeString(bstrMemberNS);
		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 Csoap12testsvcrpcObj::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, bstrMemberNS;
	VariantInit(&varContent);
	for (pIwmsoapstructIn->GetFirstMemberQN(&bstrMemberName, &bstrMemberNS, &varContent, &lPos, &bResult);
			bResult == VARIANT_TRUE;
			pIwmsoapstructIn->GetNextMemberQN(&bstrMemberName, &bstrMemberNS, &varContent, &lPos, &bResult))
	{
		VARIANT_BOOL bSuccess;
		if (FAILED(pIwmsoapstructOut->SetMemberQN(bstrMemberName, bstrMemberNS, varContent, &bSuccess)) ||
                bSuccess == VARIANT_FALSE)
        {
		    SysFreeString(bstrMemberName);
		    SysFreeString(bstrMemberNS);
		    VariantClear(&varContent);
    		pIwmsoapstructIn->Release();
    		pIwmsoapstructOut->Release();
		    return E_FAIL;
	    }
		SysFreeString(bstrMemberName);
		SysFreeString(bstrMemberNS);
		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 Csoap12testsvcrpcObj::echoString(VARIANT inputString, VARIANT* outputString)
{
	VariantCopy(outputString, &inputString);

    return S_OK;
}

STDMETHODIMP Csoap12testsvcrpcObj::echoStringArray(VARIANT inputStringArray, VARIANT *outputStringArray)
{
	SafeArrayCopy(inputStringArray.parray, &outputStringArray->parray);
	outputStringArray->vt |= (VT_VARIANT | VT_ARRAY);

	return S_OK;
}

STDMETHODIMP Csoap12testsvcrpcObj::echoInteger(VARIANT inputInteger, VARIANT *outputInteger)
{
	VariantCopy(outputInteger, &inputInteger);

	return S_OK;
}

STDMETHODIMP Csoap12testsvcrpcObj::echoIntegerArray(VARIANT inputIntegerArray, VARIANT *outputIntegerArray)
{
	SafeArrayCopy(inputIntegerArray.parray, &outputIntegerArray->parray);
	outputIntegerArray->vt |= (VT_VARIANT | VT_ARRAY);

	return S_OK;
}

STDMETHODIMP Csoap12testsvcrpcObj::echoFloat(VARIANT inputFloat, VARIANT *outputFloat)
{
	VariantCopy(outputFloat, &inputFloat);

	return S_OK;
}

STDMETHODIMP Csoap12testsvcrpcObj::echoFloatArray(VARIANT inputFloatArray, VARIANT *outputFloatArray)
{
	SafeArrayCopy(inputFloatArray.parray, &outputFloatArray->parray);
	outputFloatArray->vt |= (VT_VARIANT | VT_ARRAY);

	return S_OK;
}

STDMETHODIMP Csoap12testsvcrpcObj::echoBase64(VARIANT inputBase64, VARIANT *outputBase64)
{
	SafeArrayCopy(inputBase64.parray, &outputBase64->parray);
	outputBase64->vt |= (VT_I1 | VT_ARRAY);

	return S_OK;
}

STDMETHODIMP Csoap12testsvcrpcObj::echoHexBinary(VARIANT inputHexBinary, VARIANT *outputHexBinary)
{
	SafeArrayCopy(inputHexBinary.parray, &outputHexBinary->parray);
	outputHexBinary->vt |= (VT_I1 | VT_ARRAY);

	return S_OK;
}

STDMETHODIMP Csoap12testsvcrpcObj::echoDate(VARIANT inputDate, VARIANT *outputDate)
{
	VariantCopy(outputDate, &inputDate);

	return S_OK;
}

STDMETHODIMP Csoap12testsvcrpcObj::echoDecimal(VARIANT inputDecimal, VARIANT *outputDecimal)
{
	VariantCopy(outputDecimal, &inputDecimal);

	return S_OK;
}

STDMETHODIMP Csoap12testsvcrpcObj::echoBoolean(VARIANT inputBoolean, VARIANT *outputBoolean)
{
	VariantCopy(outputBoolean, &inputBoolean);
	return S_OK;
}

STDMETHODIMP Csoap12testsvcrpcObj::countItems(VARIANT inputStringArray, int *nCount)
{
	SAFEARRAY *pArray = inputStringArray.parray;
    int nNumItems = pArray->rgsabound[0].cElements;
    *nCount = nNumItems;

	return S_OK;
}

STDMETHODIMP Csoap12testsvcrpcObj::getTime(BSTR bstrExtraPath, BSTR bstrQueryString, VARIANT *pReturnValue)
{
    if (wcscmp(bstrExtraPath, L"") != 0)
    {
        return E_FAIL;
    }
	time_t Time;
	time(&Time);
	struct tm *pGMT = gmtime(&Time);
    char szTemp[128];
	strftime(szTemp, 128, _T("%H:%M:%S"), pGMT);
    USES_CONVERSION;
    BSTR bstrTime = A2BSTR(szTemp);
    DATE d;
	HRESULT hRes = VarDateFromStr(bstrTime, LANG_USER_DEFAULT, VAR_TIMEVALUEONLY, &d);

    pReturnValue->vt = VT_DATE;
    pReturnValue->date = d;
    return S_OK;
}

STDMETHODIMP Csoap12testsvcrpcObj::echoDouble(VARIANT inputDouble, VARIANT *outputDouble)
{
	VariantCopy(outputDouble, &inputDouble);

	return S_OK;
}

STDMETHODIMP Csoap12testsvcrpcObj::echoDateTime(VARIANT inputDateTime, VARIANT *outputDateTime)
{
	VariantCopy(outputDateTime, &inputDateTime);

	return S_OK;
}

STDMETHODIMP Csoap12testsvcrpcObj::echoTime(VARIANT inputTime, VARIANT *outputTime)
{
	VariantCopy(outputTime, &inputTime);

	return S_OK;
}

STDMETHODIMP Csoap12testsvcrpcObj::echoAnyURI(VARIANT inputAnyURI, VARIANT *outputAnyURI)
{
	VariantCopy(outputAnyURI, &inputAnyURI);

	return S_OK;
}

STDMETHODIMP Csoap12testsvcrpcObj::echoLong(VARIANT inputLong, VARIANT *outputLong)
{
	VariantCopy(outputLong, &inputLong);

	return S_OK;
}

STDMETHODIMP Csoap12testsvcrpcObj::echoInt(VARIANT inputInt, VARIANT *outputInt)
{
	VariantCopy(outputInt, &inputInt);

	return S_OK;
}

STDMETHODIMP Csoap12testsvcrpcObj::echoShort(VARIANT inputShort, VARIANT *outputShort)
{
	VariantCopy(outputShort, &inputShort);

	return S_OK;
}

STDMETHODIMP Csoap12testsvcrpcObj::echoByte(VARIANT inputByte, VARIANT *outputByte)
{
	VariantCopy(outputByte, &inputByte);

	return S_OK;
}

STDMETHODIMP Csoap12testsvcrpcObj::echoUnsignedLong(VARIANT inputUnsignedLong, VARIANT *outputUnsignedLong)
{
	VariantCopy(outputUnsignedLong, &inputUnsignedLong);

	return S_OK;
}

STDMETHODIMP Csoap12testsvcrpcObj::echoUnsignedInt(VARIANT inputUnsignedInt, VARIANT *outputUnsignedInt)
{
	VariantCopy(outputUnsignedInt, &inputUnsignedInt);

	return S_OK;
}

STDMETHODIMP Csoap12testsvcrpcObj::echoUnsignedShort(VARIANT inputUnsignedShort, VARIANT *outputUnsignedShort)
{
	VariantCopy(outputUnsignedShort, &inputUnsignedShort);

	return S_OK;
}

STDMETHODIMP Csoap12testsvcrpcObj::echoUnsignedByte(VARIANT inputUnsignedByte, VARIANT *outputUnsignedByte)
{
	VariantCopy(outputUnsignedByte, &inputUnsignedByte);

	return S_OK;
}

STDMETHODIMP Csoap12testsvcrpcObj::isNil(VARIANT inputString, VARIANT* Result)
{
    if (inputString.vt == VT_NULL)
    {
        Result->boolVal = VARIANT_TRUE;
    }
    else
    {
        Result->boolVal = VARIANT_FALSE;
    }
    Result->vt = VT_BOOL;
    return S_OK;
}
