|
|
/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
pbagstm.h
Abstract:
This module contains the definition of the property bag stream
Author:
Keith Lau (keithlau@microsoft.com)
Revision History:
keithlau 07/09/97 created
--*/
#ifndef _PBAGSTM_H_
#define _PBAGSTM_H_
#include "cpool.h"
#define MAX_PROPERTY_NAME_LENGTH 256
typedef struct _TABLE_ENTRY { DWORD dwOffset; DWORD dwSize; DWORD dwNameSize; DWORD dwMaxSize; DWORD dwKey; WORD fFlags; WORD wIndex;
} TABLE_ENTRY, *LPTABLE_ENTRY;
typedef struct _STREAM_HEADER { DWORD dwSignature; WORD wVersionHigh; WORD wVersionLow; DWORD dwHeaderSize; DWORD dwProperties; DWORD dwDirectorySize; DWORD dwEndOfData;
} STREAM_HEADER, *LPSTREAM_HEADER;
#define _CACHE_SIZE 64
typedef enum _PROPERTY_BAG_CREATORS { PBC_NONE = 0, PBC_BUILDQ, PBC_DIRNOT, PBC_ENV, PBC_LOCALQ, PBC_MAILQ, PBC_REMOTEQ, PBC_RRETRYQ, PBC_SMTPCLI
} PROPERTY_BAG_CREATORS;
typedef enum _PROPERTY_FLAG_OPERATIONS { PFO_NONE = 0, PFO_OR, PFO_ANDNOT
} PROPERTY_FLAG_OPERATIONS;
/////////////////////////////////////////////////////////////////////////////
// CPropertyBagStream
//
class CPropertyBagStream { public: CPropertyBagStream(DWORD dwContext = 0); ~CPropertyBagStream();
static CPool Pool;
// override the mem functions to use CPool functions
void *operator new (size_t cSize) { return Pool.Alloc(); } void operator delete (void *pInstance) { Pool.Free(pInstance); }
// Reference count methods ...
ULONG AddRef(); ULONG Release(BOOL fDeleteIfZeroRef = FALSE);
HRESULT SetStreamFileName(LPSTR szStreamFileName); LPSTR GetStreamFileName() { return(m_szStreamName); }
// Mechanisms for locking and unlocking the property bag
HRESULT Lock(); HRESULT Unlock();
// Force opens the stream file if it is not already opened.
// This is useful in checking if a stream file exists.
HRESULT OpenStreamFile();
// Access to properties as a whole
HRESULT GetProperty(LPSTR pszName, LPVOID pvBuffer, LPDWORD pdwBufferLen);
HRESULT SetProperty(LPSTR pszName, LPVOID pvBuffer, DWORD dwBufferLen);
// Access to properties, providing specific access to
// portions of the property data relative to the start
// of the property data
HRESULT GetPropertyAt(LPSTR pszName, DWORD dwOffsetFromStart, LPVOID pvBuffer, LPDWORD pdwBufferLen);
HRESULT SetPropertyAt(LPSTR pszName, DWORD dwOffsetFromStart, LPVOID pvBuffer, DWORD dwBufferLen);
// Ad-hoc function to allow access to a specific DWORD of
// a property, treating the DWORD as a set of flags. The
// dwOperation argument specifies what kind of binary operation
// we would like to have performed on the original value.
// If the property does not originally exist, this function
// will fail.
HRESULT UpdatePropertyFlagsAt(LPSTR pszName, DWORD dwOffsetFromStart, DWORD dwFlags, DWORD dwOperation);
#ifdef USE_PROPERTY_ITEM_ISTREAM
// Returns an IStream interface to the desired property
// for random access
HRESULT GetIStreamToProperty(LPSTR pszName, IStream **ppIStream); #endif
BOOL DeleteStream();
private:
BOOL ReleaseStream();
HRESULT Seek(DWORD dwOffset, DWORD dwMethod);
HRESULT LoadIntoCache(DWORD dwStartIndex);
LPTABLE_ENTRY FindFromCache(DWORD dwKey, LPDWORD pdwStartIndex);
HRESULT FindFrom(LPSTR pszName, DWORD dwKey, DWORD dwStartIndex, BOOL fForward, LPVOID pvBuffer, LPDWORD pdwBufferLen, LPTABLE_ENTRY *ppEntry);
HRESULT FindFromEx(LPSTR pszName, DWORD dwKey, DWORD dwStartIndex, BOOL fForward, DWORD dwOffsetFromStart, LPVOID pvBuffer, LPDWORD pdwBufferLen, LPTABLE_ENTRY *ppEntry);
HRESULT GetRecordData(LPTABLE_ENTRY pEntry, LPVOID pvBuffer);
HRESULT GetRecordName(LPTABLE_ENTRY pEntry, LPVOID pvBuffer);
HRESULT GetRecordValue(LPTABLE_ENTRY pEntry, LPVOID pvBuffer);
HRESULT GetRecordValueAt(LPTABLE_ENTRY pEntry, DWORD dwOffsetFromStart, LPVOID pvBuffer, DWORD dwBufferLen);
HRESULT UpdateEntry(LPTABLE_ENTRY pEntry);
HRESULT UpdateHeader(); HRESULT UpdateHeaderUsingHandle(HANDLE hStream);
HRESULT FindProperty(LPSTR pszName, LPVOID pvBuffer, LPDWORD pdwBufferLen, LPTABLE_ENTRY *ppEntry = NULL);
HRESULT FindPropertyEx(LPSTR pszName, DWORD dwOffsetFromStart, LPVOID pvBuffer, LPDWORD pdwBufferLen, LPTABLE_ENTRY *ppEntry = NULL);
HRESULT SetRecordData(LPTABLE_ENTRY pEntry, LPSTR pszName, LPVOID pvBuffer, DWORD dwBufferLen);
HRESULT SetRecordDataAt(LPTABLE_ENTRY pEntry, LPSTR pszName, DWORD dwOffsetFromStart, LPVOID pvBuffer, DWORD dwBufferLen, BOOL fNewRecord = FALSE);
HRESULT RelocateRecordData(LPTABLE_ENTRY pEntry);
HRESULT DetermineIfCacheValid(BOOL *pfCacheInvalid);
DWORD CreateKey(LPSTR pszName) { CHAR cKey[9]; DWORD dwLen = 0;
// Convert to lower case ...
while (*pszName && (dwLen < 8)) if ((*pszName >= 'A') && (*pszName <= 'Z')) cKey[dwLen++] = *pszName++ - 'A' + 'a'; else cKey[dwLen++] = *pszName++; cKey[dwLen] = '\0'; dwLen = lstrlen(cKey);
// Create the key
if (dwLen < 4) return((DWORD)cKey[dwLen - 1]); else if (dwLen < 8) return(*(DWORD *)cKey); else return(~*(DWORD *)cKey ^ *(DWORD *)(cKey + 4)); }
DWORD GetTotalHeaderSize() { return(sizeof(STREAM_HEADER) + (m_Header.dwDirectorySize * sizeof(TABLE_ENTRY))); }
// Current context
DWORD m_dwContext;
// Base file name
CHAR m_szStreamName[MAX_PATH + 1];
// Handle to stream
HANDLE m_hStream;
// Stream header
STREAM_HEADER m_Header;
// Directory caching
TABLE_ENTRY m_Cache[_CACHE_SIZE]; DWORD m_dwCacheStart; DWORD m_dwCachedItems;
// Reference counting
LONG m_lRef;
// This is a signature placed at the end to catch memory overwrite
DWORD m_dwSignature;
};
/////////////////////////////////////////////////////////////////////////////
// CPropertyItemStream
//
//
// Not everyone wants to use the property IStream, so we don't expose
// it if it's not wanted
//
#ifdef USE_PROPERTY_ITEM_ISTREAM
class CPropertyItemStream : public IStream { public:
CPropertyItemStream(LPSTR pszName, CPropertyBagStream *pBag) { m_cRef = 0;
m_pParentBag = pBeg; m_szName = pszName; m_libOffset.QuadPart = (DWORDLONG)0; }
~CPropertyItemStream() { Cleanup(); }
// IUnknown
STDMETHODIMP QueryInterface(REFIID, void**); STDMETHODIMP_(ULONG) AddRef(void); STDMETHODIMP_(ULONG) Release(void);
void Cleanup() {} HRESULT ReadOffset(void *pv, ULONG cb, ULONG *pcbRead, ULARGE_INTEGER *plibOffset); HRESULT WriteOffset(void const* pv, ULONG cb, ULONG *pcbWritten, ULARGE_INTEGER *plibOffset); HRESULT GetSize(ULARGE_INTEGER *plibSize); HRESULT CopyToOffset(IStream *pstm, ULARGE_INTEGER libOffset, ULARGE_INTEGER *plibRead, ULARGE_INTEGER *plibWritten, ULARGE_INTEGER *plibOffset); HRESULT CloneOffset(IStream **pstm, ULARGE_INTEGER libOffset);
// IStream
public: HRESULT STDMETHODCALLTYPE Read(void *pv, ULONG cb, ULONG *pcbRead); HRESULT STDMETHODCALLTYPE Write(void const* pv, ULONG cb, ULONG *pcbWritten); HRESULT STDMETHODCALLTYPE Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *pdlibNewPosition); HRESULT STDMETHODCALLTYPE SetSize(ULARGE_INTEGER libNewSize); HRESULT STDMETHODCALLTYPE CopyTo(IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten); HRESULT STDMETHODCALLTYPE Commit(DWORD grfCommitFlags); HRESULT STDMETHODCALLTYPE Revert(void); HRESULT STDMETHODCALLTYPE LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType); HRESULT STDMETHODCALLTYPE UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType); HRESULT STDMETHODCALLTYPE Stat(STATSTG * pstatstg, DWORD grfStatFlag); HRESULT STDMETHODCALLTYPE Clone(IStream **pstm); private: CPropertyBagStream *m_pParentBag;
LPSTR m_szName; ULARGE_INTEGER m_libOffset;
long m_cRef; };
#endif // USE_PROPERTY_ISTREAM
#endif
|