You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
291 lines
9.7 KiB
291 lines
9.7 KiB
//=======================================================================
|
|
//
|
|
// Copyright (c) 1998-1999 Microsoft Corporation. All Rights Reserved.
|
|
//
|
|
// File: wuvar.cpp
|
|
//
|
|
// Purpose:
|
|
//
|
|
//=======================================================================
|
|
|
|
#include <windows.h>
|
|
#include <v3stdlib.h>
|
|
#include <varray.h>
|
|
#include <wuv3.h>
|
|
|
|
//The GetNext function returns a pointer to the next variable array item in a
|
|
//variable chain. If the next variable item does not exit then this method
|
|
//return NULL.
|
|
|
|
PWU_VARIABLE_FIELD WU_VARIABLE_FIELD::GetNext
|
|
(
|
|
void
|
|
)
|
|
{
|
|
PWU_VARIABLE_FIELD pv;
|
|
|
|
//walk though the varaible field array associated with this data item
|
|
//and return the requested item or NULL if the item is not found.
|
|
pv = this;
|
|
if ( pv->id == WU_VARIABLE_END )
|
|
return NULL;
|
|
|
|
pv = (PWU_VARIABLE_FIELD)((PBYTE)pv + pv->len);
|
|
|
|
return pv;
|
|
}
|
|
|
|
//find a variable item in a variable item chain.
|
|
PWU_VARIABLE_FIELD WU_VARIABLE_FIELD::Find
|
|
(
|
|
short id //id of variable size field to search for in the variable size chain.
|
|
)
|
|
{
|
|
PWU_VARIABLE_FIELD pv;
|
|
|
|
//walk though the varaible field array associated with this data item
|
|
//and return the requested item or NULL if the item is not found.
|
|
pv = this;
|
|
|
|
//If this variable record only contains an end record then we
|
|
//need to handle it specially since the normal find loop
|
|
//updates the pv pointer before the end check is made so if
|
|
//end is the first field it can be missed.
|
|
|
|
if ( pv->id == WU_VARIABLE_END )
|
|
return ( id == WU_VARIABLE_END ) ? pv : (PWU_VARIABLE_FIELD)NULL;
|
|
|
|
do
|
|
{
|
|
if ( pv->id == id )
|
|
return pv;
|
|
|
|
//NT Bug #255962 - this prevents a non-terminal loop if the len is 0
|
|
if(NULL == pv->len)
|
|
return (PWU_VARIABLE_FIELD)NULL;
|
|
|
|
pv = (PWU_VARIABLE_FIELD)((PBYTE)pv + pv->len);
|
|
} while( (NULL != pv) && (pv->id != WU_VARIABLE_END) );
|
|
|
|
//case where caller asked to search for the WU_VARIABLE_END field
|
|
if ( (NULL != pv) && (pv->id == id) )
|
|
return pv;
|
|
|
|
return (PWU_VARIABLE_FIELD)NULL;
|
|
}
|
|
|
|
//Variable size field constructor.
|
|
|
|
_WU_VARIABLE_FIELD::_WU_VARIABLE_FIELD()
|
|
{
|
|
id = WU_VARIABLE_END;
|
|
len = sizeof(id) + sizeof(len);
|
|
}
|
|
|
|
//returns the total size of a variable field
|
|
int _WU_VARIABLE_FIELD::GetSize
|
|
(
|
|
void
|
|
)
|
|
{
|
|
PWU_VARIABLE_FIELD pv;
|
|
int iSize;
|
|
|
|
iSize = 0;
|
|
pv = this;
|
|
|
|
while( (NULL != pv) && (pv->id != WU_VARIABLE_END) )
|
|
{
|
|
//check if the len value is greater that 0 otherwise it might go in an infinite loop
|
|
if (pv->len < 1)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
iSize += pv->len;
|
|
pv = (PWU_VARIABLE_FIELD)((PBYTE)pv + pv->len);
|
|
}
|
|
|
|
if (NULL != pv)
|
|
{
|
|
iSize += pv->len;
|
|
}
|
|
|
|
return iSize;
|
|
}
|
|
|
|
//This function will seem tricky at first. The problem here is that the
|
|
//returned variable field array needs to be in a single block of memory.
|
|
//The reason that the memory must be contigous is that the variable field
|
|
//items that walk from one record to the next use the len parameter to find
|
|
//the beginning of the next variable record. This then prevents us from
|
|
//being able to simply take the pvNew pointer and add it to the variable
|
|
//field array. Instead we calulate the new needed size of the array and
|
|
//realloc the current pointer to this new size. We then copy the pvNew
|
|
//pointer into the newly sized array.
|
|
|
|
//The other problem here is that we cannot change the this pointer for the
|
|
//variable field array while inside a function handler for a variable field.
|
|
//So each structure that needs to manage variable fields needs one of these
|
|
//add functions. We could have set this up as a virtual function however this
|
|
//would have added a vtable to the structure. Since we are interested in the
|
|
//keeping the code size as small as possible this vtable is best avoided.
|
|
|
|
//This function has to be handled outside of the inventory item structure
|
|
//because the inventory item needs to be a continuous block of memory for
|
|
//file management. So when we add a variable field to the structure we also
|
|
//need to reallocate item structure. If we were to put this function into
|
|
//the inventory structure then we would not be able to do this because of
|
|
//this pointer semantics.
|
|
|
|
//Note: In order to use this function a valid pItem must already exist and
|
|
//since a pItem exits it must contain at least one variable type field which
|
|
//needs to be an end field.
|
|
|
|
void __cdecl AddVariableSizeField
|
|
(
|
|
PINVENTORY_ITEM *pItem, //pointer to inventory item variable size field chain.
|
|
PWU_VARIABLE_FIELD pvNew //pointer to new variable size field to add.
|
|
)
|
|
{
|
|
int iSize;
|
|
PWU_VARIABLE_FIELD pvTmp;
|
|
|
|
//calculate the size needed by the new variable field array
|
|
iSize = sizeof(INVENTORY_ITEM) + sizeof(WU_INV_FIXED) + (*pItem)->pv->GetSize() + pvNew->len;
|
|
|
|
//realloc array and fix up variable pointer
|
|
|
|
*pItem = (PINVENTORY_ITEM)V3_realloc(*pItem, iSize);
|
|
|
|
(*pItem)->pf = (PWU_INV_FIXED)(((PBYTE)(*pItem)) + sizeof(INVENTORY_ITEM));
|
|
|
|
//fix up the variable pointer since the underlying block
|
|
//may have been moved.
|
|
(*pItem)->pv = (PWU_VARIABLE_FIELD)(((PBYTE)*pItem) + sizeof(INVENTORY_ITEM) + sizeof(WU_INV_FIXED));
|
|
|
|
pvTmp = (*pItem)->pv;
|
|
|
|
//get a pointer to the last field in the variable field array
|
|
pvTmp = (*pItem)->pv->Find(WU_VARIABLE_END);
|
|
if ( !pvTmp )
|
|
{
|
|
//something is very wrong here the variable item array
|
|
//links are messed up some how. This should never happen
|
|
//in a production environment however we may see this
|
|
//in the course of development and testing.
|
|
throw (HRESULT)MEM_E_INVALID_LINK;
|
|
}
|
|
|
|
//copy over last field with new variable size field
|
|
memcpy(pvTmp, pvNew, pvNew->len);
|
|
|
|
//add new end type variable size field to end of array since
|
|
//we destroyed the existing one with the copy of the new
|
|
//variable size field.
|
|
|
|
pvTmp = (PWU_VARIABLE_FIELD)((PBYTE)pvTmp + pvTmp->len);
|
|
pvTmp->id = WU_VARIABLE_END;
|
|
pvTmp->len = sizeof(WU_VARIABLE_FIELD);
|
|
|
|
return;
|
|
}
|
|
|
|
//This function will seem tricky at first. The problem here is that the
|
|
//returned variable field array needs to be in a single block of memory.
|
|
//The reason that the memory must be contigous is that the variable field
|
|
//items that walk from one record to the next use the len parameter to find
|
|
//the beginning of the next variable record. This then prevents us from
|
|
//being able to simply take the pvNew pointer and add it to the variable
|
|
//field array. Instead we calulate the new needed size of the array and
|
|
//realloc the current pointer to this new size. We then copy the pvNew
|
|
//pointer into the newly sized array.
|
|
|
|
//The other problem here is that we cannot change the this pointer for the
|
|
//variable field array while inside a function handler for a variable field.
|
|
//So each structure that needs to manage variable fields needs one of these
|
|
//add functions. We could have set this up as a virtual function however this
|
|
//would have added a vtable to the structure. Since we are interested in the
|
|
//keeping the code size as small as possible this vtable is best avoided.
|
|
|
|
//This function has to be handled outside of the inventory item structure
|
|
//because the inventory item needs to be a continuous block of memory for
|
|
//file management. So when we add a variable field to the structure we also
|
|
//need to reallocate item structure. If we were to put this function into
|
|
//the inventory structure then we would not be able to do this because of
|
|
//this pointer semantics.
|
|
|
|
//Note: In order to use this function a valid pItem must already exist and
|
|
//since a pItem exits it must contain at least one variable type field which
|
|
//needs to be an end field.
|
|
|
|
void __cdecl AddVariableSizeField
|
|
(
|
|
PWU_DESCRIPTION *pDescription, //pointer to description record type variable size field.
|
|
PWU_VARIABLE_FIELD pvNew //pointer to new variable size field to add.
|
|
)
|
|
{
|
|
int iSize;
|
|
PWU_VARIABLE_FIELD pvTmp;
|
|
|
|
//calculate the size needed by the new variable field array
|
|
iSize = sizeof(WU_DESCRIPTION) + (*pDescription)->pv->GetSize() + pvNew->len;
|
|
|
|
//realloc array and fix up variable pointer
|
|
|
|
*pDescription = (PWU_DESCRIPTION)V3_realloc(*pDescription, iSize);
|
|
|
|
//fix up the variable pointer since the underlying block may have been moved.
|
|
(*pDescription)->pv = (PWU_VARIABLE_FIELD)(((PBYTE)*pDescription) + sizeof(WU_DESCRIPTION));
|
|
|
|
pvTmp = (*pDescription)->pv;
|
|
|
|
//get a pointer to the last field in the variable field array
|
|
pvTmp = (*pDescription)->pv->Find(WU_VARIABLE_END);
|
|
if ( !pvTmp )
|
|
{
|
|
//something is very wrong here the variable item array
|
|
//links are messed up some how. This should never happen
|
|
//in a production environment however we may see this
|
|
//in the course of development and testing.
|
|
throw (HRESULT)MEM_E_INVALID_LINK;
|
|
}
|
|
|
|
//copy over last field with new variable size field
|
|
memcpy(pvTmp, pvNew, pvNew->len);
|
|
|
|
//add new end type variable size field to end of array since
|
|
//we destroyed the existing one with the copy of the new
|
|
//variable size field.
|
|
|
|
pvTmp = (PWU_VARIABLE_FIELD)((PBYTE)pvTmp + pvTmp->len);
|
|
pvTmp->id = WU_VARIABLE_END;
|
|
pvTmp->len = sizeof(WU_VARIABLE_FIELD);
|
|
|
|
return;
|
|
}
|
|
|
|
//Adds a variable size field to a variable field chain.
|
|
//The format of a variable size field is:
|
|
//[(short)id][(short)len][variable size data]
|
|
//The variable field always ends with a WU_VARIABLE_END type.
|
|
|
|
PWU_VARIABLE_FIELD CreateVariableField
|
|
(
|
|
IN short id, //id of variable field to add to variable chain.
|
|
IN PBYTE pData, //pointer to binary data to add.
|
|
IN int iDataLen //Length of binary data to add.
|
|
)
|
|
{
|
|
PWU_VARIABLE_FIELD pVf;
|
|
|
|
pVf = (PWU_VARIABLE_FIELD)V3_malloc(sizeof(WU_VARIABLE_FIELD) + iDataLen);
|
|
|
|
if ( iDataLen )
|
|
memcpy(pVf->pData, pData, iDataLen);
|
|
|
|
pVf->id = id;
|
|
pVf->len = (short)(sizeof(WU_VARIABLE_FIELD) + iDataLen);
|
|
|
|
return pVf;
|
|
}
|