//+--------------------------------------------------------------------------
//
//  For conditions of distribution and use, see copyright notice
//  in Flashpix.h 
// 
//  Copyright (c) 1999 Digital Imaging Group, Inc.
// 
// Contents:    property set definitions
//
//---------------------------------------------------------------------------

#ifndef _PROPSTM_HXX_
#define _PROPSTM_HXX_
#include "props.h"
#include "../props/h/propapi.h"
#include "../props/h/propset.hxx"

class PMemoryAllocator
{
public:
    virtual void *Allocate(ULONG cbSize) = 0;
    virtual void Free(void *pv) = 0;
};

#define DEB_USER1 0x00010000
#define DEB_USER2 0x00020000

#define IsBadReadPtr(pv,cb) (pv==NULL)
#define IsBadWritePtr(pv,cb) (pv==NULL)
#define IsValidReadPtrIn(pv,cb)  (!IsBadReadPtr ((pv),(cb)))
#define IsValidPtrOut(pv,cb) (!IsBadWritePtr((pv),(cb)))
#define IsValidPtrIn(pv,cb) (TRUE)  // nothing we can check here

#define VDATESIZEREADPTRIN_LABEL(pv, cb, label, retVar) \
        if (!IsValidReadPtrIn((pv), cb)) \
        { \
            retVar = ResultFromScode(E_INVALIDARG); \
            goto label; \
        }

#define VDATEREADPTRIN_LABEL(pv, TYPE, label, retVar) \
        if (!IsValidReadPtrIn((pv), sizeof(TYPE)))  { \
            retVar = ResultFromScode(E_INVALIDARG); \
            goto label; }

#define VDATEREADPTRIN( pv, TYPE ) \
    if (!IsValidReadPtrIn( (pv), sizeof(TYPE))) \
       return (ResultFromScode(E_INVALIDARG))

#define VDATESIZEPTROUT_LABEL(pv, cb, label, retVar) \
    if (!IsValidPtrOut((pv), cb)) \
    { retVar = ResultFromScode(E_INVALIDARG); \
         goto label; }

#define GEN_VDATEPTROUT_LABEL( pv, TYPE, retval, label, retVar ) \
        if (!IsValidPtrOut( (pv), sizeof(TYPE))) \
        { retVar = (retval); \
         goto label; }

#define VDATEPTROUT( pv, TYPE ) \
    if (!IsValidPtrOut( (pv), sizeof(TYPE))) \
        return ResultFromScode(E_INVALIDARG);

#define VDATEPTROUT_LABEL( pv, TYPE, label, retVar ) \
        if (!IsValidPtrOut( (pv), sizeof(TYPE))) \
        { retVar = ResultFromScode(E_INVALIDARG); \
         goto label; }

#define VDATEPTRIN_LABEL(pv, TYPE, label, retVar) \
        if (!IsValidPtrIn((pv), sizeof(TYPE))) \
        { retVar = ResultFromScode(E_INVALIDARG); \
         goto label; }

#define GEN_VDATEREADPTRIN_LABEL(pv, TYPE, retval, label, retVar) \
        if (!IsValidReadPtrIn((pv), sizeof(TYPE))) \
        { retVar = retval; \
         goto label; }

#define GEN_VDATEPTRIN_LABEL(pv, TYPE, retval, label, retVar) \
        if (!IsValidPtrIn((pv), sizeof(TYPE))) \
        { retVar = retval; \
         goto label; }

#include <memory.h>
#define  ZeroMemory(pb,cb)  memset((pb),0,(cb))

typedef enum _PROPOP
{
    PROPOP_IGNORE = 1,
    PROPOP_DELETE = 2,
    PROPOP_INSERT = 3,
    PROPOP_MOVE   = 4,
    PROPOP_UPDATE = 5,
} PROPOP;

typedef struct tagPROPERTY_INFORMATION  // pinfo
{
    PROPID                   pid;

    ULONG                    cbprop;
    PROPOP                   operation;

} PROPERTY_INFORMATION;

#define VT_DICTIONARY (VT_VECTOR | VT_ILLEGALMASKED)



// Validate the endian flags.  Either BIGENDIAN or LITTLEENDIAN, but not
// both, must be defined as 1.

#ifdef WORDS_BIGENDIAN
#   define BIGENDIAN 1
#else
#   define BIGENDIAN 0
#endif

#if defined(BIGENDIAN)
#   ifdef LITTLEENDIAN
#       error Both BIGENDIAN & LITTLEENDIAN are defined
#   endif
#   if BIGENDIAN != 1
#       error BIGENDIAN must be set to 1 (not just defined)
#   endif
#elif defined(LITTLEENDIAN)
#   ifdef BIGENDIAN
#       error Both BIGENDIAN & LITTLEENDIAN are defined
#   endif
#   if LITTLEENDIAN != 1
#       error LITTLEENDIAN must be set to 1 (not just defined)
#   endif
#else
#   error Either BIGENDIAN or LITTLEENDIAN must be defined as 1
#endif




//+-------------------------------------------------------------------------
//
//         Class:       CMappedStream (user mode implementation)
//
//--------------------------------------------------------------------------

class CMappedStream
{
public:
    virtual VOID Open(IN NTPROP np, OUT LONG *phr) = 0;
    virtual VOID Close(OUT LONG *phr) = 0;
    virtual VOID ReOpen(IN OUT VOID **ppv, OUT LONG *phr) = 0;
    virtual VOID Quiesce(VOID) = 0;
    virtual VOID Map(IN BOOLEAN fCreate, OUT VOID **ppv) = 0;
    virtual VOID Unmap(IN BOOLEAN fFlush, IN OUT VOID **ppv) = 0;
    virtual VOID Flush(OUT LONG *phr) = 0;

    virtual ULONG GetSize(OUT LONG *phr) = 0;
    virtual VOID SetSize(IN ULONG cb, IN BOOLEAN fPersistent, IN OUT VOID **ppv, OUT LONG *phr) = 0;
    virtual VOID QueryTimeStamps(OUT STATPROPSETSTG *pspss, BOOLEAN fNonSimple) const = 0;
    virtual BOOLEAN QueryModifyTime(OUT LONGLONG *pll) const = 0;
    virtual BOOLEAN QuerySecurity(OUT ULONG *pul) const = 0;

    virtual BOOLEAN IsWriteable(VOID) const = 0;
    virtual BOOLEAN IsModified(VOID) const = 0;
    virtual VOID SetModified(VOID) = 0;
    virtual HANDLE GetHandle(VOID) const = 0;
#if DBGPROP
    virtual BOOLEAN SetChangePending(BOOLEAN fChangePending) = 0;
    virtual BOOLEAN IsNtMappedStream(VOID) const = 0;
#endif
};

//+-------------------------------------------------------------------------
// Class:       CStreamChunkList
//
// Purpose:     Used to support efficient in-place compaction/expansion of
//              property set streams for CPropertySetStorage.
//--------------------------------------------------------------------------

struct CStreamChunk             // scnk
{
    ULONG       oOld;
    LONG        cbChange;
};

class CStreamChunkList          // scl
{
public:
    CStreamChunkList(ULONG cMaxChunks, CStreamChunk *ascnk);

    CStreamChunk *GetFreeChunk(OUT NTSTATUS *pstatus);
    CStreamChunk const *GetChunk(ULONG i) const;
    ULONG Count(VOID) const;
    VOID SortByStartAddress(VOID);
    VOID Delete(VOID);

#if DBGPROP
    VOID AssertCbChangeTotal(
            CStreamChunk const *pscnk,
            ULONG cbChangeTotal) const;
#endif

private:
    ULONG         _cMaxChunks;  // elements in _ascnk
    ULONG         _cChunks;     // elements allocated from _ascnk
    CStreamChunk *_ascnk;
    BOOLEAN       _fDelete;     // TRUE if _ascnk allocated from heap
};

#define _MSTM(fn) _pmstm->fn

#define CPSS_DOWNLEVEL              0x02  // Downlevel property set.
#define CPSS_PACKEDPROPERTIES       0x04  // Packed property values
#define CPSS_DOCUMENTSUMMARYINFO    0x08  // DocumentSummaryInfo propset
#define CPSS_USERDEFINEDPROPERTIES  0x10  // DocumentSummaryInfo: second section
#define CPSS_MULTIPLESECTIONS       0x20  // Multiple property sections
#define CPSS_USERDEFINEDDELETED     0x40  // second section deleted
#define CPSS_VARIANTVECTOR          0x80  // Only for recursion


typedef enum tagLOADSTATE
{
    LOADSTATE_FAIL      = 0,  // load failed
    LOADSTATE_DONE      = 1,  // load succeeded
    LOADSTATE_BADFMTID      = 2,  // fmtid mismatch
    LOADSTATE_USERDEFINEDNOTFOUND = 3,  // user defined section missing
    LOADSTATE_USERDEFINEDDELETE   = 4,  // delete user defined section
} LOADSTATE;


typedef enum tagPATCHOP
{
    PATCHOP_COMPUTESIZE     = 0,  // just compute expanded size
    PATCHOP_ALIGNLENGTHS    = 1,  // just align string lengths
    PATCHOP_EXPAND      = 2,  // expand property in-place
} PATCHOP;

// Create a macro that tells us the type
// of OLECHARs.
 
#ifdef OLE2ANSI
#define OLECHAR_IS_UNICODE FALSE
#else
#define OLECHAR_IS_UNICODE TRUE
#endif

#if DBGPROP
BOOLEAN IsUnicodeString(WCHAR const *pwszname, ULONG cb);
BOOLEAN IsAnsiString(CHAR const *pszname, ULONG cb);
#endif


// IsOLECHARString calls IsUnicodeString or IsAnsiString,
// whichever is appropriate for this compilation.

inline BOOLEAN IsOLECHARString( OLECHAR const *posz, ULONG cb )
{
#if DBGPROP

#if OLECHAR_IS_UNICODE
    return( IsUnicodeString( posz, cb ));
#else
    return( IsAnsiString( posz, cb ));
#endif

#else // DBGPROP
    posz;  // remove compiler warnings
    cb;    // remove compiler warnings
    return TRUE;
#endif
}

class CPropertySetStream
{
public:
    CPropertySetStream(
        IN USHORT Flags, // NONSIMPLE|*1* of READ/WRITE/CREATE/CREATEIF/DELETE
        IN CMappedStream *pmstm,    // mapped stream implementation
        IN PMemoryAllocator *pma    // caller's memory allocator
        );


    VOID Close(OUT NTSTATUS *pstatus);
    VOID SetValue(
                IN ULONG cprop,
                IN PROPVARIANT const avar[],
                IN PROPERTY_INFORMATION *ppinfo,
                OUT NTSTATUS *pstatus);

    SERIALIZEDPROPERTYVALUE const *GetValue(IN PROPID pid, OUT ULONG *pcbprop,
                                            OUT NTSTATUS *pstatus);

    PROPID QueryPropid(IN OLECHAR const *poszName, OUT NTSTATUS *pstatus);
    USHORT GetCodePage(VOID) const { return(_CodePage); }

#if DBGPROP
    VOID Validate(OUT NTSTATUS *pstatus);
#else
    VOID Validate(OUT NTSTATUS *pstatus) const { *pstatus = STATUS_SUCCESS; }
#endif

    BOOLEAN IsModified(VOID) const { return(_MSTM(IsModified)()); }
    VOID Flush(OUT NTSTATUS *pstatus)
    {
        PROPASSERT(PROPSET_BYTEORDER == _pph->wByteOrder);
        _MSTM(Flush)(pstatus);
        PROPASSERT(PROPSET_BYTEORDER == _pph->wByteOrder);
    }


    VOID Open(
        OPTIONAL IN GUID const *pfmtid, // property set fmtid (create or Word95)
        OPTIONAL IN GUID const *pclsid, // CLASSID of propset code (create only)
  IN ULONG LocaleId,    // Locale Id (create only)
        OPTIONAL OUT ULONG *pOSVersion, // OS Version field in the propset header
        IN USHORT CodePage,             // CodePage of propset (create only)
        OUT NTSTATUS *pstatus);         // Return code.
    ULONG ReOpen(OUT NTSTATUS *pstatus);

    // Property Dictionary Lookup and Manipulation.
    BOOLEAN EnumeratePropids(
                IN OUT ULONG *pkey,
                IN OUT ULONG *pcprop,
                OUT PROPID *apid,
                OUT NTSTATUS *pstatus);

    OLECHAR *DuplicatePropertyName(
                IN OLECHAR const *poszName,
                IN ULONG cbName,
                OUT NTSTATUS *pstatus) const;

    BOOLEAN QueryPropertyNameBuf(
                IN PROPID pid,
                OUT OLECHAR *aocName,
                IN OUT ULONG *pcbName,
                OUT NTSTATUS *pstatus);

    BOOLEAN QueryPropertyNames(
                IN ULONG cprop,
                IN PROPID const *apid,
                OUT OLECHAR *aposz[],
                OUT NTSTATUS *pstatus);

    VOID SetPropertyNames(
                IN ULONG cprop,
                IN PROPID const *apid,
                IN OPTIONAL OLECHAR const * const aposz[],
                OUT NTSTATUS *pstatus);

    VOID QueryPropertySet(OUT STATPROPSETSTG *pspss, OUT NTSTATUS *pstatus) const;
    VOID SetClassId(IN GUID const *pclsid, OUT NTSTATUS *pstatus);
    HANDLE GetHandle(VOID) const { return(_MSTM(GetHandle)()); }
    PMemoryAllocator *GetAllocator(VOID) const { return(_pma); }

    VOID ByteSwapHeaders( IN PROPERTYSETHEADER *psh,
                          IN ULONG cbstm,
                          OUT NTSTATUS *pstatus );

    // Convert a character count to a byte count based on the _CodePage

    ULONG     CCh2CB( ULONG cch ) const
                {
                    return( _CodePage == CP_WINUNICODE
                            ? cch * sizeof( WCHAR )
                            : cch * sizeof( CHAR )
                          );
                }

    // Convert a byte count to a character count based on the _CodePage
    // If for some reason the given byte-count is odd, the return
    // value won't include that last half-character.

    ULONG     CB2CCh( ULONG cb ) const
    {
        return( _CodePage == CP_WINUNICODE
                ? cb / sizeof( WCHAR )
                : cb / sizeof( CHAR )
            );
    }
    
    
private:

    // Private methods.

    VOID      _Create(
        IN GUID const *pfmtid,
        OPTIONAL IN GUID const *pclsid,
        IN ULONG LocaleId,
        IN USHORT CodePage,
        IN LOADSTATE LoadState,
        OUT NTSTATUS *pstatus);
    BOOLEAN   _HasPropHeader(VOID) const { return(TRUE); }
    BOOLEAN   _CreateUserDefinedSection(
        IN LOADSTATE LoadState,
        IN ULONG LocaleId,
        OUT NTSTATUS *pstatus);
    VOID      _InitSection(
        IN FORMATIDOFFSET *pfo,
        IN ULONG LocaleId,
        IN BOOL  fCreateDictionary );
    
    VOID      _FixSummaryInformation(IN OUT ULONG *pcbstm, OUT NTSTATUS *pstatus);
    VOID      _FixPackedPropertySet(OUT NTSTATUS *pstatus);
    
    BOOLEAN   _FixDocPartsVector(
        IN PATCHOP PatchOp,
        IN OUT SERIALIZEDPROPERTYVALUE *pprop,
        OUT ULONG *pcbprop);
    BOOLEAN   _FixDocPartsElements(
        IN PATCHOP PatchOp,
        IN ULONG cString,
        OUT VOID *pvDst,
        IN VOID UNALIGNED const *pvSrc,
        OUT ULONG *pcbprop);
    
    BOOLEAN   _FixHeadingPairVector(
        IN PATCHOP PatchOp,
        IN OUT SERIALIZEDPROPERTYVALUE *pprop,
        OUT ULONG *pcbprop);
    BOOLEAN   _FixHeadingPairElements(
        IN PATCHOP PatchOp,
        IN ULONG cPairs,
        OUT SERIALIZEDPROPERTYVALUE *ppropDst,
        IN SERIALIZEDPROPERTYVALUE UNALIGNED const *ppropSrc,
        OUT ULONG *pcbprop);
    
    BOOLEAN   _IsMapped(VOID) const { return(_pph != NULL); }
    LOADSTATE _LoadHeader(OPTIONAL IN GUID const *pfmtid, IN BYTE Mode,
                          OUT NTSTATUS *pstatus);

    PROPERTYSECTIONHEADER *_LoadPropertyOffsetPointers(
        OUT PROPERTYIDOFFSET **pppo,
        OUT PROPERTYIDOFFSET **pppoMax,
        OUT NTSTATUS *pstatus);
    
    SERIALIZEDPROPERTYVALUE *_LoadProperty(IN PROPID pid, OUT ULONG *pcbprop,
                                           OUT NTSTATUS *pstatus);
    inline PROPERTYSECTIONHEADER *_GetSectionHeader(VOID) const;
    VOID _SearchForCodePage( OUT NTSTATUS *pstatus);
    PROPERTYSECTIONHEADER *_GetSectionHeader(IN ULONG iSection, OUT NTSTATUS *pstatus);
    FORMATIDOFFSET *_GetFormatidOffset(IN ULONG iSection) const;

    VOID     *_MapOffsetToAddress(IN ULONG oOffset) const;
    ULONG     _MapAddressToOffset(IN VOID const *pvAddr) const;

    VOID     *_MapAbsOffsetToAddress(IN ULONG oAbsolute) const;
    ULONG     _MapAddressToAbsOffset(IN VOID const *pvAddr) const;

    ULONG     _GetNewOffset(
        IN CStreamChunkList const *pscl,
        IN ULONG oOld) const;
    
    ULONG     _DictionaryEntryLength(
        IN ENTRY UNALIGNED const * pent ) const;
    

    ULONG     _DictionaryLength(
        IN DICTIONARY const *pdy,
        IN ULONG cbbuf,
        OUT NTSTATUS *pstatus) const;
    
    ENTRY UNALIGNED
    *_NextDictionaryEntry(
        IN ENTRY UNALIGNED const * pent ) const;
    
    ULONG     _CountFreePropertyOffsets(OUT NTSTATUS *pstatus);

    VOID      _DeleteMovePropertyOffsets(
        IN PROPERTY_INFORMATION const *apinfo,
        IN ULONG cprop,
        OUT NTSTATUS *pstatus);
    
    VOID      _UpdatePropertyOffsets(
        IN CStreamChunkList const *pscl,
        OUT NTSTATUS *pstatus);
    
    VOID      _InsertMovePropertyOffsets(
        IN PROPERTY_INFORMATION const *apinfo,
        IN ULONG cprop,
        IN ULONG oInsert,
        IN ULONG cpoReserve,
        OUT NTSTATUS *pstatus);
    
    VOID      _CompactStream(IN CStreamChunkList const *pscl);

    VOID      _CompactChunk(
        IN CStreamChunk const *pscnk,
        IN LONG cbChangeTotal,
        IN ULONG oOldNext);

    VOID      _PatchSectionOffsets(LONG cbChange);

    ULONG     _ComputeMinimumSize(ULONG cbstm, OUT NTSTATUS *pstatus);
#if DBGPROP
    VOID      _ValidateStructure(OUT NTSTATUS *pstatus);
    VOID      _ValidateProperties(OUT NTSTATUS *pstatus) const;
    VOID      _ValidateDictionary(OUT NTSTATUS *pstatus);
    VOID      _StatusCorruption(char *szReason, OUT NTSTATUS *pstatus) const;
#else
    VOID      _StatusCorruption(OUT NTSTATUS *pstatus) const;
#endif
    VOID      _SetModified(VOID) { _MSTM(SetModified)(); }

#if DBGPROP
public:   // public for fnEntryNameCompare only!
#endif
    BOOLEAN   _ComparePropertyNames(
        IN VOID const *pvName1,
        IN VOID const *pvName2,
                    IN BOOL fSameByteOrder,
        IN ULONG cbName) const;
#if DBGPROP
private:
#endif

    BOOLEAN   _PropertyNameLength(
                    IN VOID const *pvName,
                    OUT ULONG *pcbName) const;


    VOID      _MultiByteToWideChar(
                    IN CHAR const *pch,
                    IN ULONG cb,
                    IN USHORT CodePage,
                    OUT WCHAR **ppwc,
                    OUT ULONG *pcb,
                    OUT NTSTATUS *pstatus);

    VOID      _OLECHARToWideChar( IN OLECHAR const *poc,
                                  IN ULONG cb,
                                  IN USHORT CodePage,
                                  OUT WCHAR **ppwc,
                                  OUT ULONG *pcb,
                                  OUT NTSTATUS *pstatus)
    {        PROPASSERT( sizeof(OLECHAR) == sizeof(CHAR) );
        
        // Since OLECHAR may be MultiByte or WideChar for this
        // compilation, explicitely cast 'poc' to a CHAR* to prevent
        // a compilation error.

        _MultiByteToWideChar( (CHAR*) poc, cb, CodePage, ppwc, pcb, pstatus );
    }

    VOID      _MultiByteToOLECHAR( IN CHAR const *pch,
                                   IN ULONG cb,
                                   IN USHORT CodePage,
                                   OUT OLECHAR **ppoc,
                                   OUT ULONG *pcb,
                                   OUT NTSTATUS *pstatus)
    {
        PROPASSERT( sizeof(OLECHAR) == sizeof(WCHAR) );

        // Since OLECHAR may be MultiByte or WideChar for this
        // compilation, explicitely cast 'ppoc' to a WCHAR** to prevent
        // a compilation error.

        _MultiByteToWideChar( pch, cb, CodePage, (WCHAR**)ppoc, pcb, pstatus );
    }

    VOID      _WideCharToMultiByte( IN WCHAR const *pwc,
                                    IN ULONG cch,
                                    IN USHORT CodePage,
                                    OUT CHAR **ppch,
                                    OUT ULONG *pcb,
                                    OUT NTSTATUS *pstatus);

    VOID      _OLECHARToMultiByte( IN OLECHAR const *poc,
                                   IN ULONG cch,
                                   IN USHORT CodePage,
                                   OUT CHAR **ppch,
                                   OUT ULONG *pcb,
                                   OUT NTSTATUS *pstatus)
    {
        PROPASSERT( sizeof(OLECHAR) == sizeof(WCHAR) );

        // Since OLECHAR may be MultiByte or WideChar for this
        // compilation, explicitely cast 'poc' to a WCHAR* to prevent
        // a compilation error.

        _WideCharToMultiByte( (WCHAR*) poc, cch, CodePage, ppch, pcb, pstatus );
    }

    VOID      _WideCharToOLECHAR( IN WCHAR const *pwc,
                                  IN ULONG cch,
                                  IN USHORT CodePage,
                                  OUT OLECHAR **ppoc,
                                  OUT ULONG *pcb,
                                  OUT NTSTATUS *pstatus)
    {
        PROPASSERT( sizeof(OLECHAR) == sizeof(CHAR) );

        // Since OLECHAR may be MultiByte or WideChar for this
        // compilation, explicitely cast 'ppoc' to a CHAR** to prevent
        // a compilation error.

        _WideCharToMultiByte( pwc, cch, CodePage, (CHAR**) ppoc, pcb, pstatus );
    }


    PROPERTYSETHEADER     *_pph;
    ULONG                  _oSection;
    ULONG                  _cSection;
    USHORT                 _CodePage;
    BYTE                   _Flags;
    BYTE                   _State;
    ULONG      _cbTail;
    PMemoryAllocator      *_pma;
    CMappedStream         *_pmstm;        // user mode: replacable virtual class
};


#ifdef WINNT
VOID CopyPropertyValue(
        IN OPTIONAL SERIALIZEDPROPERTYVALUE const *pprop,
        IN ULONG cb,
        OUT SERIALIZEDPROPERTYVALUE *ppropDst,
        OUT ULONG *pcb);

ULONG PropertyLengthAsVariant(
        IN SERIALIZEDPROPERTYVALUE const *pprop,
        IN ULONG cbprop,
  IN USHORT CodePage,
        IN BYTE flags,
        OUT NTSTATUS *pstatus);
#endif

ULONG PropertyLength(
        IN SERIALIZEDPROPERTYVALUE const *pprop,
        IN ULONG cbbuf,
        IN BYTE flags,
        OUT NTSTATUS *pstatus);

//  ------------
//  PBS Routines
//  ------------

// PBS routines (Property Byte Swap) perform specialized byte-swapping
// in the big-endian build, and do nothing in the little-endian
// build (in which case they are inlined).

#ifdef BIGENDIAN

VOID PBSCopy( OUT VOID *pvDest,
              IN VOID const *pvSource,
              IN ULONG cbCopy,
              IN LONG cbByteSwap );

VOID PBSAllocAndCopy( OUT VOID **ppvDest,
                      IN VOID const *pvSource,
                      ULONG cbSize,
                      LONG cbByteSwap,
                      OUT NTSTATUS *pstatus);

VOID PBSInPlaceAlloc( IN OUT WCHAR** ppwszResult,
                      OUT WCHAR** ppwszBuffer,
                      OUT NTSTATUS *pstatus );

VOID PBSBuffer( IN OUT VOID *pv,
                IN ULONG cbSize,
                IN ULONG cbByteSwap );

#else // Little-endian build

inline VOID PBSCopy( OUT VOID *,
                     IN VOID const *,
                     IN ULONG,
                     IN LONG )
{
}

inline VOID PBSAllocAndCopy( OUT VOID **,
                             IN VOID const *,
                             ULONG,
                             LONG,
                             OUT NTSTATUS *pstatus)
{
    *pstatus = STATUS_SUCCESS;
}

inline VOID PBSInPlaceAlloc( IN OUT WCHAR**,
                             OUT WCHAR**,
                             OUT NTSTATUS *pstatus )
{
    *pstatus = STATUS_SUCCESS;
}

inline VOID PBSBuffer( IN OUT VOID *,
                       IN ULONG,
                       IN ULONG)
{
}

#endif // #ifdef BIGENDIAN ... #else


#endif // _PROPSTM_HXX_
