Click here to Skip to main content
15,886,724 members
Articles / Productivity Apps and Services / Microsoft Office

Hiding and Storing/caching of Application Specific data in MS Word 2003 documents

Rate me:
Please Sign up or sign in to vote.
3.54/5 (8 votes)
9 Oct 2008CPOL8 min read 29.1K   512   18  
Proof of concept on how the application specific (small/large amount of) data can be stored in ms word document as well as how it can be made hidden from end user’s eye.
// FileStorage.cpp : Defines the initialization routines for the DLL.
//

#include "stdafx.h"
#include "FileStorage.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

//
//TODO: If this DLL is dynamically linked against the MFC DLLs,
//		any functions exported from this DLL which call into
//		MFC must have the AFX_MANAGE_STATE macro added at the
//		very beginning of the function.
//
//		For example:
//
//		extern "C" BOOL PASCAL EXPORT ExportedFunction()
//		{
//			AFX_MANAGE_STATE(AfxGetStaticModuleState());
//			// normal function body here
//		}
//
//		It is very important that this macro appear in each
//		function, prior to any calls into MFC.  This means that
//		it must appear as the first statement within the 
//		function, even before any object variable declarations
//		as their constructors may generate calls into the MFC
//		DLL.
//
//		Please see MFC Technical Notes 33 and 58 for additional
//		details.
//


// CFileStorageApp

BEGIN_MESSAGE_MAP(CFileStorageApp, CWinApp)
END_MESSAGE_MAP()


// CFileStorageApp construction

CFileStorageApp::CFileStorageApp()
{
	// TODO: add construction code here,
	// Place all significant initialization in InitInstance
}


// The one and only CFileStorageApp object

CFileStorageApp theApp;


// CFileStorageApp initialization

BOOL CFileStorageApp::InitInstance()
{
	CWinApp::InitInstance();

	return TRUE;
}

BOOLEAN CFileStorageApp::AddDataToFile(WCHAR *pwszFileName,int typeOfData,WCHAR * data,BOOLEAN officeFile )
{
	//This function adds/embeds the DocumentID in office file.
	//The filename is obtained in pwszFileName argument.
	//The office file can be ms word or ms excel or ms powerpoint.
    //DocumentID would not be visible to the user when user opens the office file.
	//FILE *fp=_tfopen(_T("c:\\filelog.txt"),_T("a"));
	int errorcode=0;
	HRESULT hr=S_OK;
	if(officeFile==TRUE)
	{
		if(typeOfData==STRINGDATA_DOCUMENTID)
		{
			
			Sleep(100);//50
			 for(int i=0;i<MAX_RETRY;i++)
			{
				errorcode=0;
				 hr=S_FALSE;
			 hr=AddToStorage(pwszFileName,data,StreamName_DocumentID,&errorcode);
			 if(errorcode==Error_OpenFile||hr==S_OK)
			 {
				
				 if(hr==S_OK)
				 {
				     for(int retry=0;retry<20;retry++)
					 {
						 Sleep(200);
						 hr=AddToStorage(pwszFileName,data,StreamName_DocumentID,&errorcode);
					 }
					 hr=S_OK;
				 }
		 
				 break;
			  }
			 
			 Sleep(200);//50
			}

			if(hr==S_FALSE||hr == E_INVALIDARG)
			{
//				_fputts(_T("AddToStorage returns false  "),fp);
//				fclose(fp);
				return FALSE;
			}
			else
			{
//				_fputts(_T("AddToStorage returns true  "),fp);	
//				fclose(fp);
				return TRUE;
			}
		}
	}
	return TRUE;
}


HRESULT CFileStorageApp::AddToStorage(WCHAR *pwszFileName,WCHAR* pwszData,WCHAR *pwszStreamName,int* errorcode )
{
	//Ms word, excel and powerpoint files are compound files 
	//Therefore Compound fle implementation of structured storage is used.
	FILE *fp=_tfopen(_T("c:\\filelog.txt"),_T("a"));
	HRESULT		hr					= S_OK;
	IStorage*	pStorage			= NULL;
	IStorage*	pDataSpaceStorage	= NULL;
	IStream*	pStream	= NULL;
     *errorcode=0;
	 	CFile file;
	
	if ( pwszFileName == NULL )
	{
		hr = S_FALSE ;
		goto e_Exit;
	} 
	_fputts(_T("AddToStorage called  "),fp);
	//The StgOpenStorageEx function opens open an existing compound file object 
	//and get its root IStorage pointer
	
/*	
	hr = StgOpenStorageEx(	pwszFileName,							// Compound file name
							STGM_READWRITE | STGM_SHARE_EXCLUSIVE,	// file access
							STGFMT_STORAGE,							// specifies compound file
							0,
							NULL,
							0,
							IID_IStorage,							// return an IStorage reference
							(void **)&pStorage );					// receives IStorage reference
	if ( FAILED(hr) )
	{
		if(hr==STG_E_ACCESSDENIED)
		{
				_fputts(_T("access denied  "),fp);
		}
		else if((hr==STG_E_SHAREVIOLATION)||(hr==STG_E_LOCKVIOLATION))
		{
			_fputts(_T("STG_E_SHAREVIOLATION   "),fp);
		}
		else if(hr==STG_E_LOCKVIOLATION)
		{
		_fputts(_T("STG_E_LOCKVIOLATION   "),fp);
		}

		hr=S_FALSE ;
		_fputts(_T("StgOpenStorageEx failed  "),fp);
		goto e_Exit;
		
	}*/
  while(1)
	{
		
		BOOL retval=file.Open(pwszFileName,CFile::modeReadWrite|CFile::shareExclusive,NULL);
		
		      if(retval!=false)
			  {
				file.Flush();			
				  break;
			  }
		
	}
	file.Close();

	for (int nIndex = 0; nIndex < 100; nIndex++)
	{
		
			hr = StgOpenStorageEx(pwszFileName,							// Compound file name
							STGM_READWRITE | STGM_SHARE_EXCLUSIVE,	// file access
							STGFMT_STORAGE,							// specifies compound file
							0,
							NULL,
							0,
							IID_IStorage,							// return an IStorage reference
							(void **)&pStorage );					// receives IStorage reference
		if (FAILED(hr))
		{
			if ((hr == STG_E_SHAREVIOLATION)|| (hr==STG_E_LOCKVIOLATION))
			{
				Sleep(50);
			}
			else
			{
				break;
			}
		}
		else
			break;
	}
	if ( FAILED(hr) )
	{
		hr = S_FALSE ;
		*errorcode=Error_OpenFile;
		_fputts(_T("StgOpenStorageEx fail  "),fp);
		goto e_Exit;
	}
     _fputts(_T("StgOpenStorageEx sucess  "),fp);



	//Opens an existing storage object with the specified name in the specified access mode.
	//hr = pStorage->OpenStorage(	StorageName_DataStorage,
	//							NULL,
	//							STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
	//							NULL,
	//							0,
	//							&pDataSpaceStorage );

 //  _fputts(_T("OpenStorage called   "),fp);
	//if(hr==STG_E_FILENOTFOUND)
	//{
		//Creates and opens a new storage object with the specified name in the specified access mode.
		hr = pStorage->CreateStorage(	StorageName_DataStorage,
										STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_FAILIFTHERE,
										0,
										0,
										&pDataSpaceStorage );
		
   _fputts(_T("CreateStorage called  "),fp);

		if ( FAILED(hr) )
		{
			
			if(hr==STG_E_FILEALREADYEXISTS)
				_fputts(_T("CreateStorage failed  due to STG_E_FILEALREADYEXISTS"),fp);
		if(hr==STG_E_ACCESSDENIED)
      _fputts(_T("CreateStorage failed  due to access denied"),fp);
		else if(hr==STG_E_INSUFFICIENTMEMORY)
		 _fputts(_T("CreateStorage failed  due toSTG_E_INSUFFICIENTMEMORY"),fp);
		else if (hr==E_PENDING)
		 _fputts(_T("CreateStorage failed  due to E_PENDING"),fp);
		else if(hr==STG_E_INVALIDFUNCTION)
			 _fputts(_T("CreateStorage failed  due to STG_E_INVALIDFUNCTION"),fp);
		else if(hr==STG_E_INVALIDPOINTER)
			 _fputts(_T("CreateStorage failed  due to STG_E_INVALIDPOINTER"),fp);
		else if(hr==STG_E_INVALIDFLAG)
			 _fputts(_T("CreateStorage failed  due to STG_E_INVALIDFLAG"),fp);
		else if (hr==STG_E_INVALIDNAME)
			 _fputts(_T("CreateStorage failed  due to STG_E_INVALIDNAME"),fp);
		else if(hr==STG_E_INVALIDPARAMETER)
			 _fputts(_T("CreateStorage failed  due to STG_E_INVALIDPARAMETER"),fp);
		else if(hr==STG_E_REVERTED)
			 _fputts(_T("CreateStorage failed  due to STG_E_REVERTED"),fp);
		else if(hr==STG_E_TOOMANYOPENFILES)
			 _fputts(_T("CreateStorage failed  due to STG_E_TOOMANYOPENFILES"),fp);
		else if(hr==STG_S_CONVERTED)
			 _fputts(_T("CreateStorage failed  due to  STG_S_CONVERTED"),fp);

		
		_fputts(_T("CreateStorage failed  "),fp);
		     hr=S_FALSE ;
			goto e_Exit;
	}

	//Creates a stream "DocumentID" in storage "DataStorage" in 
	//file specified by pwszFileName  
streamCreate:
	hr=CreateStream(pDataSpaceStorage,&pStream,pwszStreamName);
	//	_fputts(_T("CreateStream called   "),fp);
	if ( FAILED(hr) )
	{
			hr=S_FALSE    ;
			_fputts(_T("CreateStream failed  "),fp);
			goto e_Exit;
	}
	ULONG  ulDataSize= (int)(wcslen(pwszData)+1) * sizeof(WCHAR); 
	//Writes the documentid value in stream DocumentID.
	hr=WriteToStream(pStream,(void *)pwszData,ulDataSize);
	_fputts(_T("WriteToStream called  "),fp);
	if ( FAILED(hr) )
	{
		hr=S_FALSE;
		_fputts(_T("WriteToStream failed  "),fp);
		goto e_Exit;
	}
	//saves the changes made to the file.
	hr = pStorage->Commit(STGC_DEFAULT);
	_fputts(_T("Commit called  "),fp);
	if ( FAILED(hr) )
	{
		hr=S_FALSE    ;
		_fputts(_T("Commit failed  "),fp);
		goto e_Exit;
	}

e_Exit:
	//performs the cleanup.
	fclose(fp);
	if ( pDataSpaceStorage != NULL )
	{
		pDataSpaceStorage->Release();
		pDataSpaceStorage = NULL;
	}
	if ( pStorage != NULL )
	{
		pStorage->Release();
		pStorage = NULL;
	}
	if ( pStream!= NULL )
	{
		pStream->Release();
		pStream = NULL;
	}
	return hr;
}

HRESULT CFileStorageApp::CreateStream(IStorage* pDataSpaceStorage,	IStream**	pStream, WCHAR *pwszStreamName)
{
	FILE *fp=_tfopen(_T("c:\\filelog.txt"),_T("a"));
	HRESULT	hr = S_FALSE;
	if(pDataSpaceStorage==NULL)
	{
		//hr=S_FALSE    ;
		return hr;
	}
	//hr=pDataSpaceStorage->OpenStream(pwszStreamName,NULL,
	//	     STGM_READWRITE | STGM_SHARE_EXCLUSIVE ,/*|STGM_FAILIFTHERE,*/
	//										0,
	//										pStream );

	//	 _fputts(_T("OpenStream called   "),fp);
	//if(hr==STG_E_FILENOTFOUND)
	//{
	//	
		hr = pDataSpaceStorage->CreateStream(pwszStreamName,
											STGM_READWRITE | STGM_SHARE_EXCLUSIVE |STGM_FAILIFTHERE,
											0,
											0,
											pStream );
		
      _fputts(_T("CreateStream called  "),fp);

		if ( FAILED(hr) )
		{
			hr=S_FALSE;
    if(hr==STG_E_FILEALREADYEXISTS)
      _fputts(_T("createsteram failed  due to STG_E_FILEALREADYEXISTS"),fp);
	else if(hr==STG_E_ACCESSDENIED)
      _fputts(_T("createsteram failed  due to access denied"),fp);
		else if(hr==STG_E_INSUFFICIENTMEMORY)
		 _fputts(_T("createsteram failed  due toSTG_E_INSUFFICIENTMEMORY"),fp);
		else if (hr==E_PENDING)
		 _fputts(_T("createsteram failed  due to E_PENDING"),fp);
		else if(hr==STG_E_INVALIDFUNCTION)
			 _fputts(_T("createsteram failed  due to STG_E_INVALIDFUNCTION"),fp);
		else if(hr==STG_E_INVALIDPOINTER)
			 _fputts(_T("createsteram failed  due to STG_E_INVALIDPOINTER"),fp);
		else if(hr==STG_E_INVALIDFLAG)
			 _fputts(_T("createsteram failed  due to STG_E_INVALIDFLAG"),fp);
		else if (hr==STG_E_INVALIDNAME)
			 _fputts(_T("createsteram failed  due to STG_E_INVALIDNAME"),fp);
		else if(hr==STG_E_INVALIDPARAMETER)
			 _fputts(_T("createsteram failed  due to STG_E_INVALIDPARAMETER"),fp);
		else if(hr==STG_E_REVERTED)
			 _fputts(_T("createsteram failed  due to STG_E_REVERTED"),fp);
		else if(hr==STG_E_TOOMANYOPENFILES)
			 _fputts(_T("createsteram failed  due to STG_E_TOOMANYOPENFILES"),fp);
		/*else if(hr==STG_S_CONVERTED)
			 _fputts(_T("OpenStorage failed  due to  STG_S_CONVERTED"),fp);*/

		
	}
	 //if(hr!=S_OK)
		 
	 fclose(fp);
	 return hr;
	
}


HRESULT CFileStorageApp::WriteToStream(IStream* pStream, void* pData, int ulDataSize)
{
	
	HRESULT hr = S_OK;
	ULONG pcbWritten=0;
	
	if ( pStream == NULL || pData == NULL || ulDataSize <= 0 )
	{
		hr=S_FALSE    ;
		goto e_Exit;
	}

	hr=pStream->Write( pData,ulDataSize,&pcbWritten);
	if (FAILED(hr) || (ulDataSize != pcbWritten))
	{
		    hr=S_FALSE    ;
			goto e_Exit;
	}
			
e_Exit:
	
	return hr;
}



BOOLEAN CFileStorageApp::ReadDataFromFile(WCHAR *pwszFileName,int typeOfData,WCHAR* data,ULONG ulDataSize,BOOLEAN officeFile )
{
	//This function reads the DocumentID from office file.
	//The filename is obtained in pwszFileName argument.
	HRESULT hr=S_OK;
	if(officeFile==TRUE)
	{
		if(typeOfData==STRINGDATA_DOCUMENTID)
		{
			hr=GetFromStorage(pwszFileName,(void *)data,ulDataSize,StreamName_DocumentID);
			if(hr==S_FALSE||hr == E_INVALIDARG)
				return FALSE;
			else
				return TRUE;
		}
	}
	return TRUE;
}

HRESULT CFileStorageApp::GetFromStorage(WCHAR *pwszFileName,void * pBuff,ULONG ulDataSize,WCHAR *pwszStreamName )
{
	HRESULT		hr					= S_OK;
	int			nDataSize			= 0;
	ULONG		ulReadSize			= 0;
	IStorage*	pStorage			= NULL;
	IStorage*	pDataSpaceStorage	= NULL;
	IStream*	pStream				= NULL;

	if ( pwszFileName == NULL || pwszStreamName == NULL || ulDataSize<=0||pBuff == NULL)
	{
		hr = E_INVALIDARG;
		goto e_Exit;
	}
	for (int nIndex = 0; nIndex < MAX_RETRY; nIndex++)
	{
		
			hr = StgOpenStorageEx(	pwszFileName,							// Compound file name
								STGM_DIRECT_SWMR|STGM_READ | STGM_SHARE_DENY_NONE,
								//STGM_READ | STGM_SHARE_DENY_WRITE,		// file access
								STGFMT_STORAGE,							// specifies compound file
								0,
								NULL,
								0,
								IID_IStorage,							// return an IStorage reference
								(void **)&pStorage );					// receives IStorage reference
		if (FAILED(hr))
		{
			if (hr == STG_E_SHAREVIOLATION)
			{
				Sleep(1);
			}
			else
			{
				break;
			}
		}
		else
			break;
	}
	if ( FAILED(hr) )
	{
		hr = S_FALSE ;
		goto e_Exit;
	}

    
	hr = pStorage->OpenStorage(	StorageName_DataStorage,
								NULL,
								STGM_READ | STGM_SHARE_EXCLUSIVE,
								NULL,
								0,
								&pDataSpaceStorage );
	if ( FAILED(hr) )
	{
		hr = S_FALSE ;
		goto e_Exit;
	}
	hr = pDataSpaceStorage->OpenStream(	pwszStreamName,
										NULL,
										STGM_READ | STGM_SHARE_EXCLUSIVE,
										0,
										&pStream );
	if ( FAILED(hr) )
	{
		hr = S_FALSE ;
		goto e_Exit;
	}
	//Reads the documentid from DocumentID stream
	hr=ReadFromStream(pStream,pBuff,ulDataSize);
	TCHAR *str=(TCHAR*)pBuff;

	if ( FAILED(hr) )
	{
		hr = S_FALSE ;
		goto e_Exit;
	}
	e_Exit:

	if ( pStream != NULL )
	{
		pStream->Release();
		pStream = NULL;
	}
	if ( pDataSpaceStorage != NULL )
	{
		pDataSpaceStorage->Release();
		pDataSpaceStorage = NULL;
	}
	if ( pStorage != NULL )
	{
		pStorage->Release();
		pStorage = NULL;
	}
	return hr;
}



HRESULT CFileStorageApp::ReadFromStream(IStream *pStream,void * pBuff,ULONG ulDataSize)
{

	HRESULT hr = S_OK;
	ULONG ulReadSize=0;
	if ( pStream == NULL || pBuff == NULL || ulDataSize <= 0 )
	{
		hr = E_INVALIDARG;
		
		goto e_Exit;
	}
	hr = pStream->Read(pBuff, ulDataSize, &ulReadSize );

	if (FAILED(hr) || (ulReadSize == 0) )
	{
		
			hr = S_FALSE ;
			goto e_Exit;
	}
	e_Exit:
		return hr;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
India India
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions