454 lines
11 KiB
C++
454 lines
11 KiB
C++
//+-------------------------------------------------------------------------
|
||
//
|
||
// Microsoft Windows
|
||
//
|
||
// Copyright (C) Microsoft Corporation, 1997 - 1999
|
||
//
|
||
// File: store.cxx
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
|
||
#include "precomp.h"
|
||
|
||
|
||
#define cbSTORE_OVERHEAD ( 3*sizeof(DWORD) )
|
||
|
||
|
||
LPSTORE Store_New( DWORD dwStoreSize )
|
||
{
|
||
LPSTORE lpStore;
|
||
|
||
lpStore = (LPSTORE) MemAlloc( cbSTORE_OVERHEAD + dwStoreSize );
|
||
|
||
if( lpStore )
|
||
{
|
||
lpStore->dwSize = dwStoreSize;
|
||
Store_Empty( lpStore );
|
||
}
|
||
|
||
return lpStore;
|
||
}
|
||
|
||
|
||
BOOL Store_Empty( LPSTORE lpStore )
|
||
{
|
||
if( !lpStore )
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
DbgLog1( SEV_FUNCTION, "Store_Empty: Remove: %ld bytes", lpStore->dwUsed );
|
||
|
||
lpStore->dwUsed = 0;
|
||
lpStore->dwOutOffset = 0;
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
BOOL Store_AddData( LPSTORE lpStore, LPVOID lpvData, DWORD dwDataSize )
|
||
{
|
||
// have enough room for new data?
|
||
if( lpStore->dwUsed + dwDataSize > lpStore->dwSize )
|
||
{
|
||
DbgLog3( SEV_ERROR,
|
||
"Store_AddData: not enough room, used %d new %d size %d",
|
||
lpStore->dwUsed, dwDataSize, lpStore->dwSize );
|
||
return FALSE;
|
||
}
|
||
|
||
CopyMemory( (LPVOID)( &(lpStore->ab1Store[lpStore->dwUsed]) ),
|
||
lpvData,
|
||
dwDataSize );
|
||
|
||
lpStore->dwUsed += dwDataSize;
|
||
|
||
DbgLog1( SEV_INFO, "Store_AddData: dwUsed: %ld bytes", lpStore->dwUsed );
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
DWORD Store_GetDataUsed( LPSTORE lpStore )
|
||
{
|
||
return lpStore->dwUsed;
|
||
}
|
||
|
||
DWORD
|
||
Store_GetSize(
|
||
LPSTORE lpStore
|
||
)
|
||
{
|
||
return lpStore->dwSize;
|
||
}
|
||
|
||
|
||
|
||
VOID Store_RemoveData( LPSTORE lpStore, DWORD dwLen )
|
||
{
|
||
DbgLog1( SEV_FUNCTION, "Store_RemoveData: Remove: %ld bytes", dwLen );
|
||
|
||
if( dwLen > lpStore->dwUsed )
|
||
{
|
||
Store_Empty( lpStore );
|
||
return;
|
||
}
|
||
|
||
lpStore->dwUsed -= dwLen;
|
||
lpStore->dwOutOffset = 0L;
|
||
|
||
if (lpStore->dwUsed)
|
||
{
|
||
CopyMemory( (LPVOID)( lpStore->ab1Store ),
|
||
(LPVOID)( &(lpStore->ab1Store[dwLen]) ),
|
||
lpStore->dwUsed );
|
||
}
|
||
|
||
DbgLog1( SEV_FUNCTION, "Store_RemoveData: dwUsed: %d", lpStore->dwUsed );
|
||
}
|
||
|
||
BOOL Store_GetData1Byte( LPSTORE lpStore, LPBYTE1 pb1 )
|
||
{
|
||
if( !pb1 )
|
||
return FALSE;
|
||
|
||
if( lpStore->dwOutOffset + sizeof(*pb1) > lpStore->dwUsed )
|
||
{
|
||
DbgLog2( SEV_ERROR,
|
||
"Store_GetData: get 1 failed, used %d, offset %d",
|
||
lpStore->dwUsed, lpStore->dwOutOffset );
|
||
return FALSE;
|
||
}
|
||
|
||
*pb1 = *( (LPBYTE1)(lpStore->ab1Store + lpStore->dwOutOffset) );
|
||
|
||
lpStore->dwOutOffset += sizeof( *pb1 );
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
BOOL Store_GetData2Byte( LPSTORE lpStore, LPBYTE2 pb2 )
|
||
{
|
||
if( !pb2 )
|
||
return FALSE;
|
||
|
||
if( lpStore->dwOutOffset + sizeof(*pb2) > lpStore->dwUsed )
|
||
{
|
||
DbgLog2( SEV_ERROR,
|
||
"Store_GetData: get 2 failed, used %d, offset %d",
|
||
lpStore->dwUsed, lpStore->dwOutOffset );
|
||
return FALSE;
|
||
}
|
||
|
||
CopyMemory(pb2,lpStore->ab1Store + lpStore->dwOutOffset, sizeof(*pb2));
|
||
|
||
// *pb2 = *( (LPBYTE2)(lpStore->ab1Store + lpStore->dwOutOffset) );
|
||
|
||
ChangeByteOrder( (LPBYTE1)pb2, sizeof(*pb2), sizeof(*pb2) );
|
||
|
||
lpStore->dwOutOffset += sizeof( *pb2 );
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
BOOL Store_GetData4Byte( LPSTORE lpStore, LPBYTE4 pb4 )
|
||
{
|
||
if( !pb4 )
|
||
return FALSE;
|
||
|
||
if( lpStore->dwOutOffset + sizeof(*pb4) > lpStore->dwUsed )
|
||
{
|
||
DbgLog2( SEV_ERROR,
|
||
"Store_GetData: get 4 failed, used %d, offset %d",
|
||
lpStore->dwUsed, lpStore->dwOutOffset );
|
||
return FALSE;
|
||
}
|
||
|
||
CopyMemory(pb4,lpStore->ab1Store + lpStore->dwOutOffset, sizeof(*pb4));
|
||
|
||
// *pb4 = *( (LPBYTE4)(lpStore->ab1Store + lpStore->dwOutOffset) );
|
||
|
||
ChangeByteOrder( (LPBYTE1)pb4, sizeof(*pb4), sizeof(*pb4) );
|
||
|
||
lpStore->dwOutOffset += sizeof( *pb4 );
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
BOOL Store_GetDataUuid( LPSTORE lpStore, UUID * pb )
|
||
{
|
||
if( !pb )
|
||
return FALSE;
|
||
|
||
if( lpStore->dwOutOffset + sizeof(*pb) > lpStore->dwUsed )
|
||
{
|
||
DbgLog2( SEV_ERROR,
|
||
"Store_GetData: get UUID failed, used %d, offset %d",
|
||
lpStore->dwUsed, lpStore->dwOutOffset );
|
||
return FALSE;
|
||
}
|
||
|
||
CopyMemory(pb,lpStore->ab1Store + lpStore->dwOutOffset, sizeof(*pb));
|
||
// *pb = *( (UUID *)(lpStore->ab1Store + lpStore->dwOutOffset) );
|
||
|
||
ChangeByteOrder( &pb->Data1, sizeof(pb->Data1), sizeof(pb->Data1) );
|
||
ChangeByteOrder( &pb->Data2, sizeof(pb->Data2), sizeof(pb->Data2) );
|
||
ChangeByteOrder( &pb->Data3, sizeof(pb->Data3), sizeof(pb->Data3) );
|
||
|
||
lpStore->dwOutOffset += sizeof( UUID );
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
BOOL Store_GetDataWsz( LPSTORE lpStore, LPWSTR wsz, DWORD BufferLength )
|
||
{
|
||
LPWSTR lpwsz = (LPWSTR)(lpStore->ab1Store + lpStore->dwOutOffset);
|
||
INT nLen = CbWsz(lpwsz);
|
||
|
||
if( !wsz || BufferLength < (DWORD) nLen)
|
||
return FALSE;
|
||
|
||
if( lpStore->dwOutOffset + nLen > lpStore->dwUsed )
|
||
{
|
||
DbgLog2( SEV_ERROR,
|
||
"Store_GetData: get Unicode string failed, used %d, offset %d",
|
||
lpStore->dwUsed, lpStore->dwOutOffset );
|
||
return FALSE;
|
||
}
|
||
|
||
wcsncpy( wsz, lpwsz, BufferLength / sizeof(WCHAR) );
|
||
|
||
lpStore->dwOutOffset += nLen;
|
||
|
||
ChangeByteOrder( (LPBYTE1)wsz, sizeof(WCHAR), nLen );
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
LPVOID Store_GetDataPtr( LPSTORE lpStore )
|
||
{
|
||
return (lpStore->ab1Store + lpStore->dwOutOffset);
|
||
}
|
||
|
||
|
||
VOID Store_SkipData( LPSTORE lpStore, INT nSize )
|
||
{
|
||
lpStore->dwOutOffset += nSize;
|
||
}
|
||
|
||
|
||
BOOL Store_PokeData( LPSTORE lpStore, DWORD dwOffset, LPVOID lpvData, DWORD dwDataSize )
|
||
{
|
||
if( dwOffset + dwDataSize > lpStore->dwUsed )
|
||
return FALSE;
|
||
|
||
// NOTE: data must be atomic
|
||
ChangeByteOrder( (unsigned char *) lpvData, dwDataSize, dwDataSize );
|
||
|
||
CopyMemory(
|
||
lpStore->ab1Store + dwOffset,
|
||
lpvData,
|
||
dwDataSize
|
||
);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
BOOL Store_AddData1Byte( LPSTORE lpStore, BYTE1 b1 )
|
||
{
|
||
return Store_AddData( lpStore, &b1, sizeof(b1) );
|
||
}
|
||
|
||
|
||
BOOL Store_AddData2Byte( LPSTORE lpStore, BYTE2 b2 )
|
||
{
|
||
ChangeByteOrder( (LPBYTE1)&b2, sizeof(b2), sizeof(b2) );
|
||
|
||
return Store_AddData( lpStore, &b2, sizeof(b2) );
|
||
}
|
||
|
||
|
||
BOOL Store_AddData4Byte( LPSTORE lpStore, BYTE4 b4 )
|
||
{
|
||
ChangeByteOrder( (LPBYTE1)&b4, sizeof(b4), sizeof(b4) );
|
||
|
||
return Store_AddData( lpStore, (LPBYTE1)&b4, sizeof(b4) );
|
||
}
|
||
|
||
BOOL Store_AddDataUuid( LPSTORE lpStore, UUID * puuid )
|
||
{
|
||
UUID uuid = *puuid;
|
||
|
||
ChangeByteOrder( &uuid.Data1, sizeof(uuid.Data1), sizeof(uuid.Data1) );
|
||
ChangeByteOrder( &uuid.Data2, sizeof(uuid.Data2), sizeof(uuid.Data2) );
|
||
ChangeByteOrder( &uuid.Data3, sizeof(uuid.Data3), sizeof(uuid.Data3) );
|
||
|
||
return Store_AddData( lpStore, &uuid, sizeof(UUID) );
|
||
}
|
||
|
||
|
||
BOOL Store_AddDataWsz( LPSTORE lpStore, LPWSTR wsz )
|
||
{
|
||
INT nLen = CbWsz( wsz );
|
||
WCHAR wszCopy[MAX_PATH];
|
||
|
||
SzCpyW( wszCopy, wsz );
|
||
|
||
ChangeByteOrder( (LPBYTE1)wszCopy, sizeof(WCHAR), nLen );
|
||
|
||
return Store_AddData( lpStore, wszCopy, nLen );
|
||
}
|
||
|
||
|
||
VOID Store_Delete( LPSTORE *lplpStore )
|
||
{
|
||
if( lplpStore && *lplpStore )
|
||
{
|
||
MemFree( *lplpStore );
|
||
*lplpStore = 0;
|
||
}
|
||
}
|
||
|
||
|
||
VOID ChangeByteOrder( void * pb1, UINT uAtomSize, UINT uDataSize )
|
||
{
|
||
LPBYTE1 pb1Src;
|
||
LPBYTE1 pb1Dst;
|
||
BYTE1 b1Temp;
|
||
UINT uSwaps;
|
||
|
||
// 1 byte atoms don't change order
|
||
if( uAtomSize == 1 )
|
||
return;
|
||
|
||
// go atom-by-atom, reversing the order of each byte in each atom
|
||
for(
|
||
pb1Src = LPBYTE1(pb1), pb1Dst = LPBYTE1(pb1) + uAtomSize-1;
|
||
pb1Src < LPBYTE1(pb1) + uDataSize;
|
||
pb1Src += uAtomSize-uSwaps, pb1Dst += uAtomSize+uSwaps
|
||
)
|
||
{
|
||
uSwaps = 0;
|
||
|
||
while( pb1Src < pb1Dst )
|
||
{
|
||
b1Temp = *pb1Src;
|
||
*pb1Src++ = *pb1Dst;
|
||
*pb1Dst-- = b1Temp;
|
||
|
||
uSwaps++;
|
||
}
|
||
}
|
||
}
|
||
|
||
void
|
||
Store_DumpParameter(
|
||
LPSTORE lpStore,
|
||
BYTE1 parm
|
||
)
|
||
{
|
||
unsigned Length;
|
||
unsigned Offset = 0;
|
||
char * name;
|
||
|
||
switch (parm)
|
||
{
|
||
case OBEX_PARAM_COUNT: name = "OBEX_PARAM_COUNT"; break;
|
||
case OBEX_PARAM_NAME: name = "OBEX_PARAM_NAME"; break;
|
||
case OBEX_PARAM_LENGTH: name = "OBEX_PARAM_LENGTH"; break;
|
||
case OBEX_PARAM_UNIX_TIME: name = "OBEX_PARAM_UNIX_TIME"; break;
|
||
case OBEX_PARAM_ISO_TIME: name = "OBEX_PARAM_ISO_TIME"; break;
|
||
case OBEX_PARAM_BODY: name = "OBEX_PARAM_BODY"; break;
|
||
case OBEX_PARAM_BODY_END: name = "OBEX_PARAM_BODY_END"; break;
|
||
case OBEX_PARAM_WHO: name = "OBEX_PARAM_WHO"; break;
|
||
case PRIVATE_PARAM_WIN32_ERROR: name = "private WIN32_ERROR"; break;
|
||
default: name = "unknown"; break;
|
||
}
|
||
|
||
DbgLog2(SEV_INFO, "parameter 0x%x (%s):", parm, name);
|
||
|
||
switch (parm & OBEX_PARAM_TYPE_MASK)
|
||
{
|
||
case OBEX_PARAM_UNICODE:
|
||
case OBEX_PARAM_STREAM:
|
||
{
|
||
if (lpStore->dwSize - lpStore->dwOutOffset < 2)
|
||
{
|
||
Length = lpStore->dwSize - lpStore->dwOutOffset;
|
||
}
|
||
else
|
||
{
|
||
DbgLog2(SEV_INFO, "length = %x:%x", lpStore->ab1Store[lpStore->dwOutOffset], lpStore->ab1Store[lpStore->dwOutOffset+1]);
|
||
|
||
Length = (lpStore->ab1Store[lpStore->dwOutOffset] << 8) + lpStore->ab1Store[lpStore->dwOutOffset+1];
|
||
|
||
Length -= 3; // on-wire length includes opcode and length field themselves
|
||
Offset = 2;
|
||
}
|
||
break;
|
||
}
|
||
case OBEX_PARAM_1BYTE:
|
||
{
|
||
Length = 1;
|
||
break;
|
||
}
|
||
case OBEX_PARAM_4BYTE:
|
||
{
|
||
Length = 4;
|
||
break;
|
||
}
|
||
default:
|
||
{
|
||
DbgLog( SEV_ERROR, "Store_DumpParameter is broken\n");
|
||
return;
|
||
}
|
||
}
|
||
|
||
if ((Length+Offset) > lpStore->dwSize - lpStore->dwOutOffset)
|
||
{
|
||
Length = lpStore->dwSize - lpStore->dwOutOffset - Offset;
|
||
}
|
||
|
||
const BYTES_PER_LINE = 16;
|
||
|
||
unsigned char *p = (unsigned char *) lpStore->ab1Store + lpStore->dwOutOffset + Offset;
|
||
|
||
//
|
||
// 3 chars per byte for hex display, plus an extra space every 4 bytes,
|
||
// plus a byte for the printable representation, plus the \0.
|
||
//
|
||
char Outbuf[BYTES_PER_LINE*3+BYTES_PER_LINE/4+BYTES_PER_LINE+1];
|
||
Outbuf[0] = 0;
|
||
Outbuf[sizeof(Outbuf)-1] = 0;
|
||
char * HexDigits = "0123456789abcdef";
|
||
|
||
if (Length < 32) {
|
||
|
||
unsigned Index;
|
||
for (Offset=0; Offset < Length; Offset++) {
|
||
|
||
Index = Offset % BYTES_PER_LINE;
|
||
|
||
if (Index == 0) {
|
||
|
||
DbgLog1(SEV_INFO, " %s", Outbuf);
|
||
memset(Outbuf, ' ', sizeof(Outbuf)-1);
|
||
}
|
||
|
||
Outbuf[Index*3+Index/4 ] = HexDigits[p[Offset] / 16];
|
||
Outbuf[Index*3+Index/4+1] = HexDigits[p[Offset] % 16];
|
||
Outbuf[BYTES_PER_LINE*3+BYTES_PER_LINE/4+Index] = iscntrl(p[Offset]) ? '.' : p[Offset];
|
||
}
|
||
|
||
DbgLog1(SEV_INFO, " %s", Outbuf);
|
||
DbgLog(SEV_INFO, "");
|
||
|
||
}
|
||
|
||
}
|