// echofilesvcObj.cpp : Implementation of CechofilesvcObj

#include "stdafx.h"
#include "echofilesvcObj.h"

#include "..\soap_source\DIMEPayload.h"
#include "..\wmsoapstruct\wmsoapstruct.h"
#include "..\wmsoapstruct\wmsoapstruct_i.c"
#include "comdef.h"
#include <string>
using namespace std;

// CechofilesvcObj

STDMETHODIMP CechofilesvcObj::echoDataFile(VARIANT inputDataFile, VARIANT *outputDataFile)
{
	// get pointer to struct object
	IDispatch *pIDispatch = inputDataFile.pdispVal;
	Iwmsoapstruct *pIwmsoapstruct;
	HRESULT res = pIDispatch->QueryInterface(IID_Iwmsoapstruct, (void **)&pIwmsoapstruct);
	if (FAILED(res))
	{
		return E_NOINTERFACE;
	}
	_variant_t varTemp;
	VARIANT_BOOL bResult;
	wstring wstrFilename;
	BSTR bstrMember1 = SysAllocString(L"fileName");
	BSTR bstrMember2 = SysAllocString(L"fileData");
	// now get struct members
	pIwmsoapstruct->GetMember(bstrMember1, &varTemp, &bResult);
	if (bResult == VARIANT_FALSE)
	{
		return E_FAIL;
	}
	wstrFilename = varTemp.bstrVal;
	varTemp.Clear();
	pIwmsoapstruct->GetMember(bstrMember2, &varTemp, &bResult);
	if (bResult == VARIANT_FALSE)
	{
		return E_FAIL;
	}
	// release interface ptr
	pIwmsoapstruct->Release();
	// now get file data
	VARIANT varOutputFile;
	VariantInit(&varOutputFile);
	// test vartype to see what we have
	if (varTemp.vt == VT_UNKNOWN)
	{
		// binary data sent as DIME attachment
		IUnknown *pIUnknownIn = varTemp.punkVal;
		IStorage *pIStorageIn;
		HRESULT hRes = pIUnknownIn->QueryInterface(IID_IStorage, (void **)&pIStorageIn);
		if (FAILED(hRes))
		{
			return E_NOINTERFACE;
		}
		DIMEPayload *pPayloadIn = new DIMEPayload(  pIStorageIn,
													string(""),
													string(""),
													DIME_TYPENAME_FORMAT_UNKNOWN);
		pIStorageIn->Release();
		if (pPayloadIn == NULL)
		{
			return E_FAIL;
		}
		// now create storage for output
		IStorage *pIStorageOut;
		hRes = StgCreateDocfile(NULL,
								STGM_DELETEONRELEASE | STGM_DIRECT | STGM_READWRITE| STGM_CREATE | STGM_SHARE_EXCLUSIVE,
								0,
								&pIStorageOut);
		if (FAILED(hRes))
		{
			return E_FAIL;
		}
		DIMEPayload *pPayloadOut = new DIMEPayload( pIStorageOut,
													string(""),
													string(""),
													DIME_TYPENAME_FORMAT_UNKNOWN);
		if (pPayloadOut == NULL)
		{
			pIStorageOut->Release();
			return E_FAIL;
		}
		// now copy contents
		char szTemp[4096];
		unsigned long ulNumBytes = 0;
		unsigned long ulBytesWritten = 0;
		pPayloadIn->OpenForRead();
		pPayloadOut->OpenForWrite();
		do
		{
			pPayloadIn->Read(szTemp, 4096, &ulNumBytes);
			pPayloadOut->Write(szTemp, ulNumBytes, &ulBytesWritten);
		} while (ulNumBytes == 4096);
		pPayloadIn->Close();
		pPayloadOut->Close();
		delete pPayloadIn;
		delete pPayloadOut;
		varOutputFile.punkVal = pIStorageOut;
		varOutputFile.vt = VT_UNKNOWN;
	}
	else
	{
		// binary sent as type base64Binary, passed in as (VT_ARRAY | VT_UI1)
		SafeArrayCopy(varTemp.parray, &varOutputFile.parray);
		varOutputFile.vt = (VT_ARRAY | VT_UI1);
	}
	// instantiate struct object
	Iwmsoapstruct *pIwmsoapstructOut;
	res = CoCreateInstance( CLSID_wmsoapstruct,
									NULL, CLSCTX_SERVER,
									IID_Iwmsoapstruct,
									(void **) &pIwmsoapstructOut);
	if (FAILED(res))
	{
		return E_FAIL;
	}
	varTemp.Clear();
	// filename
	varTemp = wstrFilename.c_str();
	pIwmsoapstructOut->SetMember(bstrMember1, varTemp, &bResult);
	// data
	pIwmsoapstructOut->SetMember(bstrMember2, varOutputFile, &bResult);
	VariantClear(&varOutputFile);

	SysFreeString(bstrMember1);
	SysFreeString(bstrMember2);
	// now get IDispatch pointer
	IDispatch *pIDispatchOut;
	res = pIwmsoapstructOut->QueryInterface(IID_IDispatch, (void **)&pIDispatchOut);
	if (FAILED(res))
	{
		pIwmsoapstructOut->Release();
		return E_NOINTERFACE;
	}
	// release
	pIwmsoapstructOut->Release();
	// set up variant
	outputDataFile->vt = VT_DISPATCH;
	outputDataFile->pdispVal = pIDispatchOut;
	return S_OK;
}
