Leaked source code of windows server 2003
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.
 
 
 
 
 
 

645 lines
13 KiB

/*
* V A L I D A T E . C
*
* Functions used to validate parameters on standard MAPI object methods.
*
* Used in conjunction with macros found in VALIDATE.H.
*
* Copyright 1992-93 Microsoft Corporation. All Rights Reserved.
*/
#include <_apipch.h>
/*
* FBadRgPropVal()
*
* Purpose:
* Routine to attempt to validate all of the ptrs contained in an input
* property value array, LPSPropVal
*/
/*
*BOOL
*FBadPropVal( LPSPropValue lpPropVal)
*{
* ULONG ulPropType;
* BOOL fLongMVProp = FALSE;
* ULONG cbItemType = 0;
* ULONG cMVVals;
* LPVOID FAR *lppvMVArray;
*
* switch (ulPropType = PROP_TYPE(lpPropVal->ulPropTag))
* {
* case PT_STRING8:
*
* if (IsBadStringPtrA( lpPropVal->Value.lpszA, (UINT)-1 ))
* {
* return TRUE;
* }
*
* break;
*
*
*#ifdef WIN32
* case PT_UNICODE:
*
* if (IsBadStringPtrW( lpPropVal->Value.lpszW, (UINT)-1 ))
* {
* return TRUE;
* }
* break;
*#endif
*
*
* case PT_BINARY:
*
* if (IsBadReadPtr( lpPropVal->Value.bin.lpb
* , (UINT) lpPropVal->Value.bin.cb))
* {
* return TRUE;
* }
*
* break;
*
* case PT_MV_I2: // 16 bit quantities
*
* cbItemType = sizeof(lpPropVal->Value.i);
* break;
*
*
* case PT_MV_UNICODE: // Arrays of strings
* case PT_MV_STRING8:
*
* fLongMVProp = TRUE;
*
* // Now fall thru to the 32 bit quantity code below to size the
* // top level array of ptrs
*
*
* case PT_MV_LONG: // 32 bit quantities
* case PT_MV_R4:
*
* cbItemType = sizeof(long);
* break;
*
*
* case PT_MV_BINARY: // Arrays of counted binary data
*
* fLongMVProp = TRUE;
*
* // Now fall thru to the 64 bit quantity code below to size the array
* // of ULONG lengths / ULONG ptrs that comprise the top level stream
*
*
* case PT_MV_DOUBLE: // 64 bit quantities
* case PT_MV_CURRENCY:
* case PT_MV_APPTIME:
* case PT_MV_SYSTIME:
* case PT_MV_I8:
*
* // Assert that all array elements for this case are the same size.
* Assert( sizeof( double ) == sizeof( LARGE_INTEGER ));
* cbItemType = sizeof( double );
* break;
*
*
* case PT_MV_CLSID: // 128 bit quantity
*
* cbItemType = sizeof( GUID );
* break;
*
*
* case PT_OBJECT:
* case PT_NULL:
* default:
* if (ulPropType & MV_FLAG)
* {
* return TRUE; // Unknown multivalue prop is bad
* }
*
* break;
* }
*
* if (!(ulPropType & MV_FLAG))
* {
* return FALSE;
* }
*
* // Try to validate the multivalue props
*
* // This code assumes that the count and ptr of every multivalue
* // property are in the same place.
* // Asserts check that the sizes of the grouped types above are
* // matched
*
* cMVVals = lpPropVal->Value.MVl.cValues;
* lppvMVArray = (LPVOID FAR *) (lpPropVal->Value.MVl.lpl);
*
* if (IsBadReadPtr( lppvMVArray, (UINT) (cMVVals * cbItemType)))
* {
* return TRUE;
* }
*
* if (fLongMVProp)
* {
* // Go verify the array of pointers.
* for ( ; cMVVals; cMVVals--, lppvMVArray++)
* {
* switch (ulPropType)
* {
*#ifdef WIN32
* case PT_MV_UNICODE:
*
* if (IsBadStringPtrW( (LPCWSTR) (*lppvMVArray), (UINT) -1))
* {
* return TRUE;
* }
*
* break;
*#endif
* case PT_MV_STRING8:
*
* if (IsBadStringPtrA( (LPCSTR) (*lppvMVArray), (UINT) -1))
* {
* return TRUE;
* }
*
* break;
*
* case PT_MV_BINARY:
*
* if (IsBadReadPtr( ((SBinary FAR *)(*lppvMVArray))->lpb
* , (UINT)
* ((SBinary FAR *)(*lppvMVArray))->cb))
* {
* return TRUE;
* }
* break;
* }
* }
* }
*
* return FALSE;
*}
*/
/*
* FBadRgPropVal()
*
* Purpose:
* Routine to attempt to validate all of the ptrs contained in an input
* property value array, LPSPropVal
*/
/*BOOL
*FBadRgPropVal( LPSPropValue lpPropVal,
* ULONG cValues)
*{
*
* if (IsBadReadPtr( lpPropVal, sizeof(SPropValue) * (UINT) cValues))
* {
* return TRUE;
* }
*
* // Warning! Modifies the function parameters (NOT what they point to!).
* //
* for ( ; cValues ; cValues--, lpPropVal++)
* {
* if (FBadPropVal( lpPropVal))
* {
* return TRUE;
* }
* }
*
* return FALSE;
*}
*/
/*
* FBadRglpszA()
*
* Purpose:
* Routine to attempt to validate all of the ptrs contained in an input
* array of string8 pointers, LPSTR FAR *.
*/
STDAPI_(BOOL)
FBadRglpszA( LPSTR FAR *lppszA,
ULONG cStrings)
{
if (IsBadReadPtr( lppszA, (UINT) (cStrings * sizeof(LPSTR FAR *))))
{
return TRUE;
}
/* Check for readability of each string in the array.
*
* WARNING!
* Function pointers and counts are modified (NOT what they point to).
*/
for (; cStrings; cStrings--, lppszA++)
{
if (IsBadStringPtrA( *lppszA, (UINT)-1 ))
{
return TRUE;
}
}
return FALSE;
}
/*
* FBadRglpszW()
*
* Purpose:
* Routine to attempt to validate all of the ptrs contained in an input
* array of UNICODE string pointers, LPSTR FAR *.
*/
STDAPI_(BOOL)
FBadRglpszW( LPWSTR FAR *lppszW,
ULONG cStrings)
{
if (IsBadReadPtr( lppszW, (UINT) (cStrings * sizeof(LPWSTR FAR *))))
{
return TRUE;
}
// Check for readability of each string in the array.
//
// WARNING!
// Function pointers and counts are modified (NOT what they point to).
//
for (; cStrings; cStrings--, lppszW++)
{
#ifdef MAC
if (IsBadStringPtr( *lppszW, (UINT)-1 ))
#else
if (IsBadStringPtrW( *lppszW, (UINT)-1 ))
#endif
{
return TRUE;
}
}
return FALSE;
}
/*
* FBadRowSet()
*
* Purpose:
* Routine to validate all rows of properties in a row set.
*
* NOTE! A NULL row pointer is assumed to be a VALID entry in a row set.
* A NULL row set pointer is assumed to be INVALID.
*/
STDAPI_(BOOL)
FBadRowSet( LPSRowSet lpRowSet)
{
LPSRow lpRow;
ULONG cRows;
if (IsBadReadPtr( lpRowSet, CbNewSRowSet(0)))
return TRUE;
if (IsBadWritePtr( lpRowSet, CbSRowSet(lpRowSet)))
return TRUE;
// Short cut
if (!lpRowSet->cRows)
return FALSE;
// Check each row in the set.
// cValues == 0 is valid if and only if lpProps == NULL
//
for ( lpRow = lpRowSet->aRow, cRows = lpRowSet->cRows
; cRows
; lpRow++, cRows--)
{
if ( IsBadReadPtr( lpRow, sizeof(*lpRow))
#ifndef _WIN64
|| FBadRgPropVal( lpRow->lpProps, (int) (lpRow->cValues))
#endif // _WIN64
)
{
return TRUE;
}
}
return FALSE;
}
/*
* FBadRglpNameID()
*
* Purpose:
* Routine to attempt to validate all of the ptrs contained in an input
* array of MAPINAMEID pointers, LPMAPINAMEID FAR *.
*/
STDAPI_(BOOL)
FBadRglpNameID( LPMAPINAMEID FAR * lppNameId,
ULONG cNames)
{
if (IsBadReadPtr( lppNameId, (UINT) (cNames * sizeof(LPMAPINAMEID FAR *))))
{
return TRUE;
}
// Check for readability of each string in the array.
//
for (; cNames; cNames--, lppNameId++)
{
LPMAPINAMEID lpName = *lppNameId;
if (IsBadReadPtr(lpName, sizeof(MAPINAMEID)))
{
return TRUE;
}
if (IsBadReadPtr(lpName->lpguid, sizeof(GUID)))
{
return TRUE;
}
if (lpName->ulKind != MNID_ID && lpName->ulKind != MNID_STRING)
{
return TRUE;
}
if (lpName->ulKind == MNID_STRING)
{
if (IsBadStringPtrW( lpName->Kind.lpwstrName, (UINT)-1 ))
{
return TRUE;
}
}
}
return FALSE;
}
/* FBadEntryList moved to src\lo\msvalid. */
/*============================================================================
* The following functions are used to determine the validity of various
* table-related structures. These functions should most definitely
* be moved to proputil when it becomes a lib (or DLL).
*/
/*============================================================================
- FBadPropTag()
-
* Returns TRUE if the specified prop tag isn't one of the known
* MAPI property types, FALSE otherwise.
*
*
* Parameter:
* ulPropTag in Proptag to validate.
*/
STDAPI_(ULONG)
FBadPropTag( ULONG ulPropTag )
{
// Just check the type
switch ( PROP_TYPE(ulPropTag) & ~MV_FLAG )
{
default:
return TRUE;
case PT_UNSPECIFIED:
case PT_NULL:
case PT_I2:
case PT_LONG:
case PT_R4:
case PT_DOUBLE:
case PT_CURRENCY:
case PT_APPTIME:
case PT_ERROR:
case PT_BOOLEAN:
case PT_OBJECT:
case PT_I8:
case PT_STRING8:
case PT_UNICODE:
case PT_SYSTIME:
case PT_CLSID:
case PT_BINARY:
return FALSE;
}
}
/*============================================================================
- FBadRow()
-
* Returns TRUE if the specified row contains invalid (PT_ERROR or
* PT_NULL) columns or if any of those columns are invalid.
*
*
* Parameter:
* lprow in Row to validate.
*/
STDAPI_(ULONG)
FBadRow( LPSRow lprow )
{
LPSPropValue lpprop;
LPSPropValue lppropT;
if ( IsBadReadPtr(lprow, sizeof(SRow)) ||
IsBadReadPtr(lprow->lpProps, (size_t)(lprow->cValues * sizeof(SPropValue))) )
return TRUE;
lpprop = lprow->lpProps + lprow->cValues;
while ( lpprop-- > lprow->lpProps )
{
if ( FBadProp(lpprop) )
return TRUE;
lppropT = lpprop;
while ( lppropT-- > lprow->lpProps )
if ( lppropT->ulPropTag == lpprop->ulPropTag &&
PROP_TYPE(lppropT->ulPropTag) != PT_ERROR &&
PROP_TYPE(lppropT->ulPropTag) != PT_NULL )
{
DebugTrace( TEXT("FBadRow() - Row has multiple columns with same proptag!\n") );
return TRUE;
}
}
return FALSE;
}
/*============================================================================
- FBadProp()
-
* Returns TRUE if the specified property is invalid.
*
*
* Parameters:
* lpprop in Property to validate.
*/
STDAPI_(ULONG)
FBadProp( LPSPropValue lpprop )
{
ULONG ulcb;
LPVOID lpv;
if ( IsBadReadPtr(lpprop, sizeof(SPropValue)) ||
FBadPropTag(lpprop->ulPropTag) )
return TRUE;
switch ( PROP_TYPE(lpprop->ulPropTag) )
{
default:
return FALSE;
case PT_BINARY:
ulcb = lpprop->Value.bin.cb;
lpv = lpprop->Value.bin.lpb;
break;
case PT_STRING8:
ulcb = sizeof(CHAR);
lpv = lpprop->Value.lpszA;
break;
#ifndef WIN16
case PT_UNICODE:
ulcb = sizeof(WCHAR);
lpv = lpprop->Value.lpszW;
break;
#endif
case PT_CLSID:
ulcb = sizeof(GUID);
lpv = lpprop->Value.lpguid;
break;
case PT_MV_I2:
case PT_MV_LONG:
case PT_MV_R4:
case PT_MV_DOUBLE:
case PT_MV_CURRENCY:
case PT_MV_I8:
ulcb = UlPropSize(lpprop);
lpv = lpprop->Value.MVi.lpi;
break;
case PT_MV_BINARY:
{
LPSBinary lpbin;
if ( IsBadReadPtr(lpprop->Value.MVbin.lpbin,
(size_t)(lpprop->Value.MVbin.cValues *
sizeof(SBinary))) )
return TRUE;
lpbin = lpprop->Value.MVbin.lpbin + lpprop->Value.MVbin.cValues;
while ( lpprop->Value.MVbin.lpbin < lpbin-- )
if ( IsBadReadPtr(lpbin->lpb, (size_t)(lpbin->cb) ))
return TRUE;
return FALSE;
}
case PT_MV_STRING8:
{
LPCSTR FAR * lppsz;
if ( IsBadReadPtr(lpprop->Value.MVszA.lppszA,
(size_t)(lpprop->Value.MVszA.cValues * sizeof(LPSTR))) )
return TRUE;
lppsz = lpprop->Value.MVszA.lppszA + lpprop->Value.MVszA.cValues;
while ( lpprop->Value.MVszA.lppszA < lppsz-- )
// Need to break the code up this way for the Mac version
if ( IsBadReadPtr(*lppsz, sizeof(CHAR)))
return TRUE;
return FALSE;
}
case PT_MV_UNICODE:
{
UNALIGNED LPWSTR FAR * lppsz;
if ( IsBadReadPtr(lpprop->Value.MVszW.lppszW,
(size_t)(lpprop->Value.MVszW.cValues * sizeof(LPWSTR))) )
return TRUE;
lppsz = lpprop->Value.MVszW.lppszW + lpprop->Value.MVszW.cValues;
while ( lpprop->Value.MVszW.lppszW < lppsz-- )
if ( IsBadReadPtr(*lppsz, sizeof(WCHAR)))
return TRUE;
return FALSE;
}
}
return IsBadReadPtr(lpv, (size_t) ulcb);
}
/* FBadSortOrderSet moved to src\lo\MSVALID.C */
/*============================================================================
- FBadColumnSet()
-
* Returns TRUE if the specified column set is invalid. For use
* with IMAPITable::SetColumns(), this function treats PT_ERROR columns
* as invalid and PT_NULL columns as valid.
*
*
* Parameter:
* lpptaCols in Column set to validate.
*/
STDAPI_(ULONG)
FBadColumnSet( LPSPropTagArray lpptaCols )
{
UNALIGNED ULONG FAR * pulPropTag;
if ( IsBadReadPtr(lpptaCols,CbNewSPropTagArray(0)) ||
IsBadReadPtr(lpptaCols,CbSPropTagArray(lpptaCols)))
{
DebugTrace( TEXT("FBadColumnSet() - Bad column set structure\n") );
return TRUE;
}
// maximum number of proptags we can calculate size for. raid 4460
if ( lpptaCols->cValues > ((INT_MAX - offsetof( SPropTagArray, aulPropTag ))
/ sizeof( ULONG )))
{
DebugTrace( TEXT("FBadColumnSet(): Exceeded maximum number of tags\n") );
return TRUE;
}
pulPropTag = lpptaCols->aulPropTag + lpptaCols->cValues;
while ( pulPropTag-- > lpptaCols->aulPropTag )
{
// DCR 978: Disallow PT_ERROR columns.
// DCR 715: Ignore PT_NULL columns and only allow columns
// from initial column set.
if ( PROP_TYPE(*pulPropTag) != PT_NULL &&
(PROP_TYPE(*pulPropTag) == PT_ERROR ||
FBadPropTag(*pulPropTag)) )
{
DebugTrace( TEXT("FBadColumnSet() - Bad column 0x%08lX\n"), *pulPropTag );
return TRUE;
}
}
return FALSE;
}