Click here to Skip to main content
15,896,503 members
Articles / Programming Languages / C++

Structured Storage File Viewer Visual Studio Add-In

Rate me:
Please Sign up or sign in to vote.
4.83/5 (6 votes)
3 Dec 2001CPOL6 min read 132K   2.8K   41  
Visual Studio add-in that allows you to view the contents of a Structured Storage File.
// Commands.cpp : implementation file
//

#include "stdafx.h"
#include "SSFView.h"
#include "Commands.h"
#include "Dlg_StructuredStorageFileViewer.h"
#include <commdlg.h>



#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CCommands

CCommands::CCommands()
{
	m_pApplication = NULL;
	m_pApplicationEventsObj = NULL;
	m_pDebuggerEventsObj = NULL;
	m_pDlg_StructuredStorageFileViewer = NULL;
}

CCommands::~CCommands()
{
	ASSERT (m_pApplication != NULL);
	m_pApplication->Release();
}

void CCommands::SetApplicationObject(IApplication* pApplication)
{
	// This function assumes pApplication has already been AddRef'd
	//  for us, which CDSAddIn did in its QueryInterface call
	//  just before it called us.
	m_pApplication = pApplication;

	// Create Application event handlers
	XApplicationEventsObj::CreateInstance(&m_pApplicationEventsObj);
	m_pApplicationEventsObj->AddRef();
	m_pApplicationEventsObj->Connect(m_pApplication);
	m_pApplicationEventsObj->m_pCommands = this;

	// Create Debugger event handler
	CComPtr<IDispatch> pDebugger;
	if (SUCCEEDED(m_pApplication->get_Debugger(&pDebugger)) 
		&& pDebugger != NULL)
	{
		XDebuggerEventsObj::CreateInstance(&m_pDebuggerEventsObj);
		m_pDebuggerEventsObj->AddRef();
		m_pDebuggerEventsObj->Connect(pDebugger);
		m_pDebuggerEventsObj->m_pCommands = this;
	}
}

void CCommands::UnadviseFromEvents()
{
	ASSERT (m_pApplicationEventsObj != NULL);
	m_pApplicationEventsObj->Disconnect(m_pApplication);
	m_pApplicationEventsObj->Release();
	m_pApplicationEventsObj = NULL;

	if (m_pDebuggerEventsObj != NULL)
	{
		// Since we were able to connect to the Debugger events, we
		//  should be able to access the Debugger object again to
		//  unadvise from its events (thus the VERIFY_OK below--see stdafx.h).
		CComPtr<IDispatch> pDebugger;
		VERIFY_OK(m_pApplication->get_Debugger(&pDebugger));
		ASSERT (pDebugger != NULL);
		m_pDebuggerEventsObj->Disconnect(pDebugger);
		m_pDebuggerEventsObj->Release();
		m_pDebuggerEventsObj = NULL;
	}
}


/////////////////////////////////////////////////////////////////////////////
// Event handlers

// TODO: Fill out the implementation for those events you wish handle
//  Use m_pCommands->GetApplicationObject() to access the Developer
//  Studio Application object

// Application events

HRESULT CCommands::XApplicationEvents::BeforeBuildStart()
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
	return S_OK;
}

HRESULT CCommands::XApplicationEvents::BuildFinish(long nNumErrors, long nNumWarnings)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
	return S_OK;
}

HRESULT CCommands::XApplicationEvents::BeforeApplicationShutDown()
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
	m_pCommands -> BeforeApplicationShutdown();
	return S_OK;
}

HRESULT CCommands::XApplicationEvents::DocumentOpen(IDispatch* theDocument)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
	return S_OK;
}

HRESULT CCommands::XApplicationEvents::BeforeDocumentClose(IDispatch* theDocument)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
	return S_OK;
}

HRESULT CCommands::XApplicationEvents::DocumentSave(IDispatch* theDocument)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
	return S_OK;
}

HRESULT CCommands::XApplicationEvents::NewDocument(IDispatch* theDocument)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
	return S_OK;
}

HRESULT CCommands::XApplicationEvents::WindowActivate(IDispatch* theWindow)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
	return S_OK;
}

HRESULT CCommands::XApplicationEvents::WindowDeactivate(IDispatch* theWindow)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
	return S_OK;
}

HRESULT CCommands::XApplicationEvents::WorkspaceOpen()
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
	return S_OK;
}

HRESULT CCommands::XApplicationEvents::WorkspaceClose()
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
	return S_OK;
}

HRESULT CCommands::XApplicationEvents::NewWorkspace()
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
	return S_OK;
}

// Debugger event

HRESULT CCommands::XDebuggerEvents::BreakpointHit(IDispatch* pBreakpoint)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
	return S_OK;
}


/////////////////////////////////////////////////////////////////////////////
// CCommands methods

STDMETHODIMP CCommands::SSFViewCommandMethod() 
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());

	// TODO: Replace this with the actual code to execute this command
	//  Use m_pApplication to access the Developer Studio Application object,
	//  and VERIFY_OK to see error strings in DEBUG builds of your add-in
	//  (see stdafx.h)

	VERIFY_OK(m_pApplication->EnableModeless(VARIANT_FALSE));
	::MessageBox(NULL, "SSFView Command invoked.", "SSFView", MB_OK | MB_ICONINFORMATION);
	VERIFY_OK(m_pApplication->EnableModeless(VARIANT_TRUE));
	return S_OK;
}

STDMETHODIMP CCommands::StructuredStorageFileViewer()
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	// TODO: Add your implementation code here
    if (m_pDlg_StructuredStorageFileViewer == NULL)
	{
	  LPTSTR lpszFileName = NULL;
	  long lRetTemp = 0;

	  lRetTemp = OpenAFile ((LPTSTR*)&lpszFileName);

	  if ((lRetTemp == 0) && (lpszFileName))
	  {
	    m_pDlg_StructuredStorageFileViewer = new CDlg_StructuredStorageFileViewer();
		m_pDlg_StructuredStorageFileViewer -> SetFileToView((LPCTSTR)lpszFileName);
	    m_pDlg_StructuredStorageFileViewer -> SetCommandsObject (this);
	    m_pDlg_StructuredStorageFileViewer -> Display();
	  }

	  if (lpszFileName)
	  {
	    free (lpszFileName);
		lpszFileName = NULL;
	  }
	}

	return S_OK;
}

long CCommands::OpenFileInWindow(LPCTSTR lpszFileName, LPCTSTR lpszOpenAs, BOOL bReadOnly)
{
	VARIANT varRetVal;
	VARIANT varOpenAs;
    VARIANT varReadOnly;
	EXCEPINFO excepInfo; 	// this variable contains exception info if any Invoke call fails
	char szOutput[80];
	DISPPARAMS dispparams = { NULL, NULL, 0, 0 };
	DISPID dispid;
	LPOLESTR szDispatchNameDocument = L"Documents";
	LPOLESTR szDispatchNameOpen = L"Open";
	IDispatch* pDocuments = NULL;
	IUnknown* pUnk = NULL;
	HRESULT hr;
	VARIANTARG varg[3];
	DISPPARAMS dpOpen = { varg, NULL, 3, 0 };
	long lRet = 0;
	int iRetTemp = 0;
	OLECHAR* lpWideCharStr = NULL;
	OLECHAR* lpWideCharStr2 = NULL;

    iRetTemp = MultiByteToWideChar
	(
	  (UINT)CP_ACP, // code page 
      (DWORD)MB_PRECOMPOSED, // character-type options 
      (LPCSTR)lpszFileName, // address of string to map 
      (int)(-1), // number of characters in string 
      (LPWSTR)lpWideCharStr, // address of wide-character buffer 
      (int)0 // size of buffer 
    );

    lpWideCharStr = (OLECHAR*)malloc ((iRetTemp + 1)* sizeof(OLECHAR));

	if (lpWideCharStr == NULL)
	{
	  lRet = -1;  // Insufficient memory to convert string to OLE string.
	  goto OpenFileInWindow_0;
	}

    iRetTemp = MultiByteToWideChar
	(
	  (UINT)CP_ACP, // code page 
      (DWORD)MB_PRECOMPOSED, // character-type options 
      (LPCSTR)lpszFileName, // address of string to map 
      (int)(-1), // number of characters in string 
      (LPWSTR)lpWideCharStr, // address of wide-character buffer 
      (int)iRetTemp // size of buffer 
    );

	if (iRetTemp == 0)
	{
	  lRet = -2;  // Error in conversion from single byte character to wide character.
	  goto OpenFileInWindow_0;
	}

    iRetTemp = MultiByteToWideChar
	(
	  (UINT)CP_ACP, // code page 
      (DWORD)MB_PRECOMPOSED, // character-type options 
      (LPCSTR)lpszOpenAs, // address of string to map 
      (int)(-1), // number of characters in string 
      (LPWSTR)lpWideCharStr2, // address of wide-character buffer 
      (int)0 // size of buffer 
    );

    lpWideCharStr2 = (OLECHAR*)malloc ((iRetTemp + 1)* sizeof(OLECHAR));

	if (lpWideCharStr2 == NULL)
	{
	  lRet = -1;  // Insufficient memory to convert string to OLE string.
	  goto OpenFileInWindow_0;
	}

    iRetTemp = MultiByteToWideChar
	(
	  (UINT)CP_ACP, // code page 
      (DWORD)MB_PRECOMPOSED, // character-type options 
      (LPCSTR)lpszOpenAs, // address of string to map 
      (int)(-1), // number of characters in string 
      (LPWSTR)lpWideCharStr2, // address of wide-character buffer 
      (int)iRetTemp // size of buffer 
    );

	if (iRetTemp == 0)
	{
	  lRet = -2;  // Error in conversion from single byte character to wide character.
	  goto OpenFileInWindow_0;
	}

	VariantInit(&varRetVal);

	hr = m_pApplication -> GetIDsOfNames(IID_NULL, &szDispatchNameDocument, 1, LOCALE_SYSTEM_DEFAULT, &dispid);
	if (hr != S_OK)
	{
	  sprintf (szOutput, "GetIDsOfNames() failed. hr == 0x%X", hr);
	  AfxMessageBox(szOutput, 
	  	MB_OK | MB_ICONINFORMATION);

	  goto OpenFileInWindow_0;
	}

	hr = m_pApplication -> Invoke 
	(
	  dispid, 
	  IID_NULL, 
	  LOCALE_SYSTEM_DEFAULT, 
	  DISPATCH_PROPERTYGET, 
	  &dispparams, 
	  &varRetVal, 
	  &excepInfo, 
	  NULL
	);

    if (hr != S_OK)
	{
	  sprintf (szOutput, "Invoke() failed. hr == 0x%X.", hr);
	  AfxMessageBox(szOutput, 
	  	MB_OK | MB_ICONINFORMATION);

	  goto OpenFileInWindow_0;
	}

    pDocuments = varRetVal.pdispVal;

	VariantInit(&varRetVal);

	hr = pDocuments -> GetIDsOfNames(IID_NULL, &szDispatchNameOpen, 1, LOCALE_SYSTEM_DEFAULT, &dispid);
	if (hr != S_OK)
	{
	  sprintf (szOutput, "pDocument -> GetIDsOfNames() failed. hr == 0x%X", hr);
	  AfxMessageBox(szOutput, 
	    MB_OK | MB_ICONINFORMATION);

	  goto OpenFileInWindow_0;
	}
    
	VariantInit(&(varg[2]));
	varg[2].vt = VT_BSTR;
	varg[2].bstrVal = SysAllocString(lpWideCharStr);

	VariantInit(&(varg[1]));
	VariantInit(&varOpenAs);
	varOpenAs.vt = VT_BSTR;
	varOpenAs.bstrVal = SysAllocString(lpWideCharStr2);
	varg[1].vt = VT_BYREF|VT_VARIANT;
	varg[1].pvarVal = &varOpenAs;

	VariantInit(&(varg[0]));
	VariantInit(&varReadOnly);
	varReadOnly.vt = VT_BOOL;
	if (bReadOnly)
	  varReadOnly.boolVal = (VARIANT_BOOL)(-1);
	else 
	  varReadOnly.boolVal = (VARIANT_BOOL)0;
	varg[0].vt = VT_BYREF|VT_VARIANT;
	varg[0].pvarVal = &varReadOnly;

	hr = pDocuments -> Invoke 
	(
	  dispid, 
	  IID_NULL, 
	  LOCALE_SYSTEM_DEFAULT, 
	  DISPATCH_METHOD, 
	  &dpOpen, 
	  &varRetVal, 
	  &excepInfo, 
	  NULL
	);

	pUnk = varRetVal.pdispVal;

	SysFreeString (varg[2].bstrVal);
	SysFreeString (varOpenAs.bstrVal);

    if (hr != S_OK)
	{
	  sprintf (szOutput, "pDocuments -> Invoke() failed. hr == 0x%X.", hr);
	  AfxMessageBox(szOutput, 
	  	MB_OK | MB_ICONINFORMATION);
	}

OpenFileInWindow_0:

    if (pDocuments)
	{
	  pDocuments -> Release();
	  pDocuments = NULL;
	}

	if (pUnk)
	{
	  pUnk -> Release();
	  pUnk = NULL;
	}

	if (lpWideCharStr)
	{
	  free (lpWideCharStr);
	  lpWideCharStr = NULL;
	}

	if (lpWideCharStr2)
	{
	  free (lpWideCharStr2);
	  lpWideCharStr2 = NULL;
	}

	return lRet;
}

long CCommands::BeforeApplicationShutdown()
{
	long lRet = 0;

	if (m_pDlg_StructuredStorageFileViewer)
	{
      delete m_pDlg_StructuredStorageFileViewer;
	  m_pDlg_StructuredStorageFileViewer = NULL;
	}

	return lRet;
}

long CCommands::SSF_NotifyViewerDialogClosing()
{
	long lRet = 0;

	if (m_pDlg_StructuredStorageFileViewer)
	{
      delete m_pDlg_StructuredStorageFileViewer;
	  m_pDlg_StructuredStorageFileViewer = NULL;
	}

	return lRet;
}

long CCommands::OpenAFile(LPTSTR *ppFileNameReceiver)
{
  OPENFILENAME	ofn;
  LPTSTR		lpszFileName = NULL;
  long			lRet = 0;

  *ppFileNameReceiver = NULL;

  lpszFileName = (LPTSTR)malloc(_MAX_PATH * sizeof(TCHAR));
  memset (lpszFileName, 0, _MAX_PATH * sizeof(TCHAR));

  memset (&ofn, 0, sizeof(OPENFILENAME));
  ofn.lStructSize = sizeof(OPENFILENAME);
  ofn.hwndOwner = NULL;
  ofn.hInstance = AfxGetResourceHandle();
  ofn.lpstrFilter = NULL;  // No filter needed.
  ofn.lpstrFile = lpszFileName;
  ofn.nMaxFile = _MAX_PATH;
  ofn.Flags = OFN_FILEMUSTEXIST;

  if (GetOpenFileName((LPOPENFILENAME)&ofn))
  {
    *ppFileNameReceiver = lpszFileName;
  }
  else
  {
    DWORD dwLastError = GetLastError();

    free (lpszFileName);
	lRet = -1;  // Something went wrong.
  }

  return lRet;
}

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
Systems Engineer NEC
Singapore Singapore
Lim Bio Liong is a Specialist at a leading Software House in Singapore.

Bio has been in software development for over 10 years. He specialises in C/C++ programming and Windows software development.

Bio has also done device-driver development and enjoys low-level programming. Bio has recently picked up C# programming and has been researching in this area.

Comments and Discussions