350 lines
8.1 KiB
C++
350 lines
8.1 KiB
C++
/*++
|
|
|
|
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
|
|
|