/*
*********************************************************************
*
*	The Essence of OLE
*
*	Source code sample
*
*	Copyright (c) 1996, Rolling Thunder Computing, Ipswich MA
*
*	e-mail: essence@rollthunder.com
*	CompuServe: 73540,3430
*	Web: http://www.rollthunder.com
*
*	File Name: CPERFILE.CPP
*
*	Purpose: Implementation of IPersistFile interface
*
*********************************************************************
*/

#include <windows.h>
#include "cfiletextdata.h"

extern CLSID CLSID_MonikerSv ;
extern HWND hEdit ;

STDMETHODIMP CFileTextData::Load (LPCOLESTR pFileName, DWORD grfMode)
{  

	HRESULT hr ;

/*
Remember name we are given.
*/
	wcscpy (m_wFileName, pFileName) ;

/*
Open existing storage file.
*/

	IStorage *pStor ;

	hr = StgOpenStorage (pFileName, NULL,
		STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
		NULL, 0, &pStor) ;

	if (!SUCCEEDED(hr))
	{
		MessageBox (NULL, "This app only opens file that it created.", "Error", MB_ICONSTOP) ;
		return E_FAIL ;
	}

/*
Open a stream within the storage file.
*/
	IStream *pStream ;

	hr = pStor->OpenStream (L"Text", 0, 
		STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 
 		0, &pStream) ;

  	if (!SUCCEEDED(hr))
	{
		MessageBox (NULL, "Could not create storage file", "Error", MB_ICONSTOP) ;
		return E_FAIL ;
	}

/*
Find length of stream, allocate enough memory to hold its contents.
Read file text from stream. Make sure it is NULL-terminated.
Release storage and stream.
*/
	ULARGE_INTEGER ul ;
	LARGE_INTEGER l_zero = {0, 0} ;

	pStream->Seek (l_zero, STREAM_SEEK_END, &ul) ;
	pStream->Seek (l_zero, STREAM_SEEK_SET, NULL) ;

	m_length = ul.LowPart+1	;
	m_cp = (char *)GlobalAlloc (GMEM_FIXED, m_length) ;
	if (!m_cp)
	{
		return E_OUTOFMEMORY ;
	}
	pStream->Read (m_cp, m_length-1, NULL) ;
	*(m_cp + ul.LowPart) = 0 ;
	
	pStor->Release ( ) ;
	pStream->Release ( ) ;

/*
Create new moniker based on current file name.  Make entry for
new file in ROT
*/

	CreateFileMoniker (pFileName, &m_pFileMoniker) ;

	LPRUNNINGOBJECTTABLE pROT ;

	GetRunningObjectTable (0, &pROT) ;				
			
	pROT->Register (0,	// flags,
		(LPDATAOBJECT)this,								// running object
		m_pFileMoniker,		// moniker of running object
		&m_dwRegisterROT) ;	// output variable 

	pROT->Release ( ) ;
/*
Place object's data into main window's edit control.
*/
	SetWindowText (hEdit, m_cp) ;


	return S_OK ;
}


STDMETHODIMP CFileTextData::GetCurFile(LPOLESTR * ppszFile)
{
    LPMALLOC    pIMalloc;
    WCHAR *      pWchar;
	HRESULT		hr ;


/*
Get the current memory allocator from OLE
*/

	hr =  CoGetMalloc(MEMCTX_SHARED, &pIMalloc)	;
    
	if (hr != S_OK)
	{
      *ppszFile = NULL;
      return E_FAIL ;
	}


/*
Use the IMalloc to allocate a block of shareable memory that can be
passed to another file and is big enough to hold a file name.  Then 
release the allocator.
*/
    pWchar = (WCHAR *)pIMalloc->Alloc (256*sizeof (WCHAR));
    pIMalloc->Release();

/*
Copy the file name into the memory block.  Return a pointer to the memory
block in the output variable.
*/

	wcscpy (pWchar, m_wFileName) ;
	*ppszFile = pWchar;
    
	return  NOERROR;
}


STDMETHODIMP CFileTextData::GetClassID(LPCLSID pClsID)
{
    *pClsID = CLSID_MonikerSv ;
    return NOERROR;
}


STDMETHODIMP CFileTextData::IsDirty(void)
{
    return S_FALSE ;
}

STDMETHODIMP CFileTextData::Save(LPCOLESTR pFileName, BOOL fRemember)
{

	HRESULT hr ;

/*
Remember name we are saved under.
*/
	if (fRemember)
	{
		wcscpy (m_wFileName, pFileName) ;
	}

/*
Create new storage file. Mark with our server's class ID
*/

	IStorage *pStor ;

	hr = StgCreateDocfile (m_wFileName, 
			STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE,
			0, &pStor) ;

	if (!SUCCEEDED(hr))
	{
		MessageBox (NULL, "Could not create storage file", "Error", MB_ICONSTOP) ;
		return 0 ;
	}

	pStor->SetClass (CLSID_MonikerSv) ;

/*
Open a stream within the storage file.
*/
	IStream *pStream ;

	hr = pStor->CreateStream (L"Text", 
		STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 
 		 0, 0, &pStream) ;

  	if (!SUCCEEDED(hr))
	{
		MessageBox (NULL, "Could not create stream within file", "Error", MB_ICONSTOP) ;
		return 0 ;
	}

/*
Get data from edit control, write into stream.  Release storage and stream.
*/
	pStream->Write (m_cp, m_length, NULL) ;

	pStream->Release ( ) ;
	pStor->Release ( ) ;


	return S_OK ;
}


STDMETHODIMP CFileTextData::SaveCompleted(LPCOLESTR pszFile)
{
    return NOERROR;
}
