II. Header file describing Office 97 Binder file format
/*************************************************************************
**
** Office 97 Binder
**
** datadef.h
**
** (c) Copyright Microsoft Corp. 1996 All Rights Reserved
**
*************************************************************************/
// Number of elements in an array
#define ARRAYSIZE(a) (sizeof(a)/sizeof((a)[0]))
// Maximum size of a string within Binder. Nominally used for LoadString calls.
#define MAX_STR_SIZE 256
#define MAX_SHELL_FILENAME_LEN 250
#define MAX_FILENAME_LEN 256 // Including NULL
#define MAX_PATH_LEN MAX_PATH // Including NULL, drive, colon, leading seperator.
#define MAX_FILE_LEN MAX_PATH_LEN
#define MAX_MENUNAME_LEN 64 // Including NULL
#define MAX_EXT_SIZE 4
#define MAX_STATUS_SIZE MAX_STR_SIZE
// {59850400-6664-101B-B21C-00AA004BA90B} + NULL.
// The number of TEXT characters that a CLSID will be represented by.
#define MAX_CLSID_STR_LEN 39
// CWSTORAGENAME is the maximum amount allowed for a sub-storage. It is currently
// defined as 32 characters INCLUDING the NULL.
#define MAX_SECTION_STG_NAME CWCSTORAGENAME
#define MAX_SECTION_STG_CHARS (MAX_SECTION_STG_NAME - 1)
#define MAX_SECTION_DISPLAY_NAME MAX_FILENAME_LEN
#define MAX_SECTION_DISPLAY_CHARS (MAX_SECTION_DISPLAY_NAME - 1)
#define APPMAJORVERSIONNO 8 // major no. incremented for major releases
// (eg. when an incompatible change is made
// to the storage format)
#define APPMINORVERSIONNO 0 // minor no. incremented for minor releases
#define APPMINIMUMVERSIONNO 5 // minimum version # that this version of app can read
#define BDRTYPELIBMAJORVERNO 8 // major ver. # for Binder Typelib
#define BDRTYPELIBMINORVERNO 0 // minor ver. # for Binder Typelib
typedef struct{
int SectionIndex;
char SectionName[MAX_SECTION_DISPLAY_NAME];
} SECTIONDATA, *PSECTIONDATA;
typedef enum tagSAVE_TYPE{
SAVE_SAME = 0,
SAVE_AS = 1,
SAVE_COPY_AS = 2
}SAVE_TYPE;
#define LOAD_NEW_FILE_FROM_TEMPLATE 0x0001
#define LOAD_READONLY 0x0002
#define LOAD_APPLY_FRAME_POS 0x0004
#define LOAD_DISPLAY_ERRORS 0x0008
// struct definition for persistent data storage of Binder data
// Format of Binder stream.
//
// 1)DOCHEADER
// 2)SECTION_RECORD
// 3)History list for that section (used by Reconciler)
// .
// .
// ... for as many sections as are present, repeat 2 and 3 for all sections
// and all deleted sections.
// Stored in Binder stream. Opened and read by CDocument::FLoadFromStg.
typedef struct tagDOCHEADER {
DWORD m_dwLength; // Length (in bytes) of the structure
LONG m_narrAppVersionNo[2];
LONG m_narrMinAppVersionNo[2];
GUID m_guidBinderId; // The unique ID of the binder
DWORD m_cSections;
DWORD m_cDeletedSections;
LONG m_nActiveSection;
LONG m_nFirstVisibleTab; // in the left pane
FILETIME m_TotalEditTime; // amount of time file is open for edit
FILETIME m_CreateTime; // Time Created
FILETIME m_LastPrint; // When last printed
FILETIME m_LastSave; // When last saved
DWORD m_dwState; // remember state info like left pane visibility
DWORD m_reserved[3]; // space reserved for future use
} DOCHEADER, * PDOCHEADER;
// Stored in Binder stream. 1 per Section. Read by CSection::Load
typedef struct tagSECTIONRECORD
{
DWORD m_dwLength; // Length (in bytes) of all the
// data that make up a section.
// It includes the size of the
// SECTIONNAMERECORD and of the
// history list.
GUID m_guidSectionId; // The unique ID of the section
DWORD m_dwState; // state of this section
DWORD m_dwStgNumber;
// Unique stg number for this section
DWORD m_reserved1; // space reserved for future use
DWORD m_reserved2; // space reserved for future use
DWORD m_reserved3; // space reserved for future use
DWORD m_reserved4; // space reserved for future use
DWORD m_dwDisplayNameOffset;
// Offset to the SECTIONNAMERECORD
// from the beggining of this struct.
DWORD m_dwHistoryListOffset;
// Offset to the history list
// from the beggining of this struct.
// Display name
// History list
} SECTIONRECORD, * PSECTIONRECORD;
typedef struct tagSECTIONNAMERECORD
{
DWORD m_dwNameSize; // Size of variable length
// Display name
// Display name of size m_dwNameSize
} SECTIONNAMERECORD, * PSECTIONNAMERECORD;
// Stored in binder stream. 1 per deleted section (used for Reconciler)
typedef struct tagDELETEDSECTIONRECORD
{
DWORD m_dwLength;
// Length in bytes of all the
// data that make up a section
// It includes the size of the
// SECTIONNAMERECORD and of the
// history list.
GUID m_guidSectionId;// The unique ID of the section
DWORD m_reserved1; // space reserved for future use
DWORD m_reserved2; // space reserved for future use
DWORD m_reserved3; // space reserved for future use
DWORD m_reserved4; // space reserved for future use
DWORD m_dwDisplayNameOffset; // Offset to the SECTIONNAMERECORD
// from the beggining of this struct.
DWORD m_dwHistoryListOffset; // Offset to the history list
// from the beggining of this struct.
// Display name
// History list
} DELETEDSECTIONRECORD, * PDELETEDSECTIONRECORD;
struct CGenericMetaSection
{
public:
CGenericMetaSection(LPSTREAM pStm, LONG *narrAppVersionNo)
{
m_pStm = pStm;
m_narrAppVersionNo[0] = narrAppVersionNo[0];
m_narrAppVersionNo[1] = narrAppVersionNo[1];
}
virtual ~CGenericMetaSection() {};
/*
* Read the current record. The stream must be positioned at the
* beginning of the record to be read.
*/
HRESULT ReadRecord()
{
HRESULT hrErr;
LARGE_INTEGER libZero = {0,0};
if (SUCCEEDED(hrErr = m_pStm->Seek(libZero, STREAM_SEEK_CUR,
&m_libStart)))
{
hrErr = m_pStm->Read(GetRecordAddress(), GetRecordSize(), NULL);
}
return hrErr;
}
/*
* Seek to the beginning of the display name structure
*/
HRESULT SeekDisplayName()
{
return SeekOffset(GetDisplayNameOffset());
}
/*
* Seek to the beginning of the history list structure
*/
HRESULT SeekHistoryList()
{
return SeekOffset(GetHistoryListOffset());
}
/*
* Should only be called after ReadRecord has been called. This function
* will position the stream at the end of the current record, no matter
* what its current position is. ReadRecord can be called again after
* SkipCurrentRecord is called in order to get the next record.
*/
HRESULT SkipCurrentRecord()
{
return SeekOffset(GetTotalSectionSize());
}
virtual PVOID GetRecordAddress() = 0;
virtual DWORD GetRecordSize() = 0;
protected:
/*
* Seek to a given offset from the beginning of the section record
*/
HRESULT SeekOffset(DWORD dwOffset)
{
LARGE_INTEGER libTemp = {0,0};
libTemp.LowPart = m_libStart.LowPart + dwOffset;
return m_pStm->Seek(libTemp, STREAM_SEEK_SET, NULL);
}
virtual DWORD GetTotalSectionSize() = 0;
virtual DWORD GetDisplayNameOffset() = 0;
virtual DWORD GetHistoryListOffset() = 0;
ULARGE_INTEGER m_libStart;
LPSTREAM m_pStm;
LONG m_narrAppVersionNo[2];
};
struct CMetaSectionRecord: public CGenericMetaSection, public tagSECTIONRECORD
{
public:
CMetaSectionRecord(LPSTREAM pStm, LONG *narrAppVersionNo)
: CGenericMetaSection(pStm, narrAppVersionNo) {};
virtual PVOID GetRecordAddress()
{ return (tagSECTIONRECORD*)this; }
virtual DWORD GetRecordSize()
{ return sizeof SECTIONRECORD; }
protected:
virtual DWORD GetTotalSectionSize() { return m_dwLength; }
virtual DWORD GetDisplayNameOffset() { return m_dwDisplayNameOffset; }
virtual DWORD GetHistoryListOffset() { return m_dwHistoryListOffset; }
};
struct CMetaDeletedSectionRecord: public CGenericMetaSection,
public tagDELETEDSECTIONRECORD
{
public:
CMetaDeletedSectionRecord(LPSTREAM pStm, LONG *narrAppVersionNo)
: CGenericMetaSection(pStm, narrAppVersionNo) {};
virtual PVOID GetRecordAddress()
{ return (tagDELETEDSECTIONRECORD*)this; }
virtual DWORD GetRecordSize()
{ return sizeof DELETEDSECTIONRECORD; }
protected:
virtual DWORD GetTotalSectionSize() { return m_dwLength; }
virtual DWORD GetDisplayNameOffset() { return m_dwDisplayNameOffset; }
virtual DWORD GetHistoryListOffset() { return m_dwHistoryListOffset; }
};
// Persistent section flags: DO NOT MODIFY THE VALUES
typedef enum {
SECTIONSTATE_VISIBLE = 0x00000001L,
SECTIONSTATE_SELECTED = 0x00000002L,
SECTIONSTATE_ACTIVE = 0x00000004L,
SECTIONSTATE_USEGLOBALHDRFTR = 0x00000008L,
// Does the section use the global Header/Footer (only valid if FSupportHdrFtr() is TRUE).
SECTIONSTATE_CREATEFROMOLE = 0x01000000L
// When section is Run, re-create from file.
} SECTIONSTATE;
/////////////////////////////////////////////////////////////////////////////
// OLE 2.0 COM (Component Object Model) implementation infrastructure.
// Taken from MFC (afxdisp.h) and extended.
#define _AFX_NO_NESTED_DERIVATION
#define METHOD_PROLOGUE(theClass, localClass) \
theClass* pThis = \
((theClass*)((BYTE*)this - offsetof(theClass, m_x##localClass)));
#ifndef _AFX_NO_NESTED_DERIVATION
#define METHOD_PROLOGUE_EX(theClass, localClass) \
theClass* pThis = ((theClass*)((BYTE*)this - m_nOffset));
#else
#define METHOD_PROLOGUE_EX(theClass, localClass) \
METHOD_PROLOGUE(theClass, localClass)
#endif
#define BEGIN_INTERFACE_PART(localClass, baseClass) \
class X##localClass : public baseClass \
{ \
public: \
STDMETHOD_(ULONG, AddRef)(); \
STDMETHOD_(ULONG, Release)(); \
STDMETHOD(QueryInterface)(REFIID iid, PVOID* ppvObj);
#ifdef _DEBUG
#define IMPLEMENT_DEBUG_ADDREF \
m_cRef++;
#define IMPLEMENT_DEBUG_RELEASE \
Assert(m_cRef > 0); \
m_cRef--;
#else
#define IMPLEMENT_DEBUG_ADDREF
#define IMPLEMENT_DEBUG_RELEASE
#endif /* !_DEBUG */
#define IMPLEMENT_INTERFACE_PART_EX(theClass, localClass, addref, release, qi) \
ULONG theClass::X##localClass::AddRef() { \
METHOD_PROLOGUE_EX(theClass, localClass) \
IMPLEMENT_DEBUG_ADDREF \
return pThis->addref(); \
} \
ULONG theClass::X##localClass::Release() { \
METHOD_PROLOGUE_EX(theClass, localClass) \
IMPLEMENT_DEBUG_RELEASE \
return pThis->release(); \
} \
STDMETHODIMP theClass::X##localClass::QueryInterface(REFIID iid, void **ppvObj) { \
METHOD_PROLOGUE_EX(theClass, localClass) \
return pThis->qi(iid, ppvObj); \
}
#define IMPLEMENT_INTERFACE_PART(theClass, localClass) \
IMPLEMENT_INTERFACE_PART_EX(theClass, localClass, AddRef, \
Release, QueryInterface)
// Section uses these macros
#define IMPLEMENT_SECTION_INTERFACE_PART_EX(theClass, localClass, addref, release, qi) \
ULONG theClass::X##localClass::AddRef() { \
hrIllegalSectionCallChk(); \
METHOD_PROLOGUE_EX(theClass, localClass) \
IMPLEMENT_DEBUG_ADDREF \
return pThis->addref(); \
} \
ULONG theClass::X##localClass::Release() { \
dwIllegalSectionCallChk(); \
METHOD_PROLOGUE_EX(theClass, localClass) \
IMPLEMENT_DEBUG_RELEASE \
return pThis->release(); \
} \
STDMETHODIMP theClass::X##localClass::QueryInterface(REFIID iid, void **ppvObj) { \
dwIllegalSectionCallChk(); \
METHOD_PROLOGUE_EX(theClass, localClass) \
return pThis->qi(iid, ppvObj); \
}
#define IMPLEMENT_SECTION_INTERFACE_PART(theClass, localClass) \
IMPLEMENT_SECTION_INTERFACE_PART_EX(theClass, localClass, AddRef, \
Release, QueryInterface)
//
#ifdef _DEBUG
#define DEFINE_REFCOUNT \
ULONG m_cRef;
#else
#define DEFINE_REFCOUNT
#endif
#ifndef _AFX_NO_NESTED_DERIVATION
#define INIT_INTERFACE_PART(theClass, localClass) \
DEFINE_REFCOUNT \
size_t m_nOffset; \
X##localClass() \
{ m_nOffset = offsetof(theClass, m_x##localClass); }
#else
#define INIT_INTERFACE_PART(theClass, localClass) \
DEFINE_REFCOUNT
#endif
// Note: Inserts the rest of OLE functionality between these two macros,
// depending upon the interface that is being implemented. It is not
// necessary to include AddRef, Release, and QueryInterface since those
// member functions are declared by the macro.
#define END_INTERFACE_PART(localClass) \
} m_x##localClass; \
friend class X##localClass;
*************