|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionA Structured Storage File is a binary file that is created and managed by the Microsoft OLE Structured Storage APIs. Structured Storage Files are also known as Compound Files. Essentially, we have a "file system within a file". Within such a compound file, we have two types of named objects: Storages and Streams. A Storage Object acts like a directory of a typical file system. It manages other storages and streams but holds no data by itself. A Stream Object acts like a file in that it can hold information but not other storage objects. Examples of compound files include Microsoft Word (.doc) documents and Microsoft Excel (.xls) worksheet files. SSFView is a Visual Studio add-in that allows a developer to view the contents of Structured Storage Files. An example view of a Microsoft Word document is shown in the screenshot above. The motivation for the development of this add-in came about when my development team had to debug the implementation of a program data file which is stored using OLE's Structured Storage File format. For debugging purposes, we had to compare stream outputs from existing storage files with live stream data being created. We had to dump out parts of stream data using trace statements and other file logging operations. It was messy and the use of these debugging constructs were short-termed. We thus took the initiative to develop our own Structured Storage File Viewer which can be customized to meet our debugging needs. We thought it would be a good idea to share our code to readers out there who may be facing similar problems and would wish to have some startup code in order to develop a customized Structured Storage File Viewer. Instead of developing a separate application, it was our unanimous choice to develop an add-in instead. The following are the advantages:
Installation
Usage
LimitationsNote that double-clicking the same stream item will cause its contents to be displayed even if its contents have already been displayed in a binary view window. The contents of a stream object are first dumped by the add-in into a temporary file on your system. The contents of this file is displayed in the binary view window. Therefore the title of the window will be the name of the temp file and not the name of the stream object. How It WorksThe entire functionality of the add-in is encapsulated inside the 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;
}
A new instance of The void CDlg_StructuredStorageFileViewer::OnSelchangedTreeStructuredStorageFileContents (NMHDR* pNMHDR, LRESULT* pResult) { NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; // TODO: Add your control notification handler code here HWND hwndTree = pNMHDR -> hwndFrom; // If a selection in the Tree has changed, we investigate further. if (pNMHDR -> code == TVN_SELCHANGED) { // If this item is designated as a Storage item, // we analyse it further. if ((pNMTreeView -> itemNew).lParam == STGTY_STORAGE) { // AnalyseStorage() will insert further Tree Items inside this item // if appropriate. AnalyseStorageItem ((HWND)hwndTree, (pNMTreeView -> itemNew).hItem); } if ((pNMTreeView -> itemNew).lParam == STGTY_STREAM) { // AnalyseStreamItem() will display the // IStream information of this stream item. AnalyseStreamItem ((HWND)hwndTree, (pNMTreeView -> itemNew).hItem); } } *pResult = 0; return; } Two functions stand out:
The void CDlg_StructuredStorageFileViewer::OnDblclkTreeStructuredStorageFileContents (NMHDR* pNMHDR, LRESULT* pResult) { // TODO: Add your control notification handler code here HWND hwndTree = pNMHDR -> hwndFrom; HTREEITEM hTreeItemCurrent = TreeView_GetSelection(hwndTree); TV_ITEM tv_item_current; memset (&tv_item_current, 0, sizeof(TV_ITEM)); tv_item_current.hItem = hTreeItemCurrent; tv_item_current.mask = TVIF_HANDLE | TVIF_PARAM; TreeView_GetItem (hwndTree, &tv_item_current); // If this item is designated as a Storage item, // we analyse it further. if (tv_item_current.lParam == STGTY_STORAGE) { // Nothing needs to be done when a Storage Item is double-clicked. // It has already been analysed in TVN_SELCHANGED. } if (tv_item_current.lParam == STGTY_STREAM) { // When a Stream Item is double-clicked, // its contents will have to be displayed. DisplayStreamItem ((HWND)hwndTree, (HTREEITEM)hTreeItemCurrent); } *pResult = 0; return; } Only when a Stream object is double-clicked will any meaningful thing be performed. We display the
contents of this stream object when it is double-clicked. The main function to perform this is
ConclusionA tree view provides a natural and intuitive layout for directories and files and this is the primary reason why we use it to display storages and streams. However, the emphasis of this add-in is to view and save data. Therefore nothing fancy is done with the tree view control. This can be seen in the fact that although we used MFC's We also did not make extensive use of private item data ( HTREEITEM CDlg_StructuredStorageFileViewer::TreeItemInsert_Storage
(HWND hwndTree, LPCTSTR lpszStorageName, HTREEITEM hTreeItemParent)
{
TV_INSERTSTRUCT tvis ;
...
...
...
>>tvis.item.lParam = STGTY_STORAGE;
hTreeItemRet = TreeView_InsertItem(hwndTree, &tvis);
return hTreeItemRet;
}
We plan to further enhance the statistics information display. The various date/time values are
currently displayed as hex values. This is because we have yet to find out how to properly interpret
We also plan to extend our add-in to read memory storages and streams which can prove very useful as well.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||