Windows2003-3790/inetcore/outlookexpress/wabw/wabapi/mapiutil.c
2020-09-30 16:53:55 +02:00

518 lines
11 KiB
C

/*
* MAPI 1.0 property handling routines
*
*
* MAPIUTIL.C -
*
* Useful routines for manipulating and comparing property values continued
* The difference between this file and proputil.c is that this file doesn't require
* any c-runtimes.
*/
#include <_apipch.h>
#ifndef MB_SETFOREGROUND
#define MB_SETFOREGROUND 0
#endif
STDAPI_(BOOL)
FEqualNames(LPMAPINAMEID lpName1, LPMAPINAMEID lpName2)
{
AssertSz(lpName1 && !IsBadReadPtr(lpName1, sizeof(MAPINAMEID)),
TEXT("lpName1 fails address check"));
AssertSz(lpName2 && !IsBadReadPtr(lpName2, sizeof(MAPINAMEID)),
TEXT("lpName2 fails address check"));
//
// Same ptr case - optimization
if (lpName1 == lpName2)
return TRUE;
if (memcmp(lpName1->lpguid, lpName2->lpguid, sizeof(GUID)))
return FALSE;
if (lpName1->ulKind == lpName2->ulKind)
{
if (lpName1->ulKind == MNID_STRING)
{
if (!lstrcmpW(lpName1->Kind.lpwstrName,
lpName2->Kind.lpwstrName))
{
return TRUE;
}
} else
{
if (lpName1->Kind.lID == lpName2->Kind.lID)
{
return TRUE;
}
}
}
return FALSE;
}
/*
* IsBadBoundedStringPtr
*
* Like IsBadStringPtr, but guarantees in addition that there is a
* valid string which will fit in a buffer of cchMax characters.
*/
BOOL WINAPI EXPORT_16
IsBadBoundedStringPtr(const void FAR *lpsz, UINT cchMax)
{
if (IsBadStringPtr(lpsz, (UINT) -1) || ((UINT) lstrlenA(lpsz) >= cchMax))
return TRUE;
return FALSE;
}
/*
* For now, internal to HrQueryAllRows.
*
* Merges prows with *pprowsDst, reallocating *pprowsDst if
* necessary. Destroys the container portion of prows (but not the
* individual rows it contains).
*/
HRESULT // STDAPI
HrMergeRowSets(LPSRowSet prows, LPSRowSet FAR *pprowsDst)
{
SCODE sc = S_OK;
LPSRowSet prowsT;
UINT crowsSrc;
UINT crowsDst;
Assert(!IsBadWritePtr(pprowsDst, sizeof(LPSRowSet)));
Assert(prows);
if (!*pprowsDst || (*pprowsDst)->cRows == 0)
{
// This is easy. But check this case first, because if the
// table is completely empty we want to return this.
FreeBufferAndNull(pprowsDst); // correct, no '&'
*pprowsDst = prows;
prows = NULL; // don't free it!
goto ret;
}
if (prows->cRows == 0)
{
// This is easy too
goto ret;
}
// OK, now we know there are rows in both rowsets.
// We have to do a real merge.
SideAssert(crowsSrc = (UINT) prows->cRows);
crowsDst = (UINT) (*pprowsDst)->cRows; // handle 0
if (FAILED(sc = MAPIAllocateBuffer(CbNewSRowSet(crowsSrc + crowsDst),
&prowsT)))
goto ret;
if (crowsDst)
CopyMemory(prowsT->aRow, (*pprowsDst)->aRow, crowsDst*sizeof(SRow));
CopyMemory(&prowsT->aRow[crowsDst], prows->aRow, crowsSrc*sizeof(SRow));
prowsT->cRows = crowsSrc + crowsDst;
FreeBufferAndNull(pprowsDst); // correct, no '&'
*pprowsDst = prowsT;
ret:
FreeBufferAndNull(&prows);
DebugTraceSc(HrMergeRowSets, sc);
return ResultFromScode(sc);
}
/*
- HrQueryAllRows
-
* Purpose:
* Retrieves all rows from an IMAPITable interface up to a set
* maximum. It will optionally set the column set, sort order,
* and restriction on the table before querying.
*
* If the table is empty, an SRowSet with zero rows is
* returned (just like QueryRows).
*
* The seek position of the table is undefined both before and
* after this call.
*
* If the function fails with an error other than
* MAPI_E_NOT_ENOUGH_MEMORY, extended error information is
* available through the table interface.
*
* Arguments:
* ptable in the table interface to query
* ptaga in if not NULL, column set for the table
* pres in if not NULL, restriction to be applied
* psos in if not NULL, sort order to be applied
* crowsMax in if nonzero, limits the number of rows
* to be returned.
* pprows out all rows of the table
*
* Returns:
* HRESULT. Extended error information normally is in the
* table.
*
* Side effects:
* Seek position of table is undefined.
*
* Errors:
* MAPI_E_TABLE_TOO_BIG if the table contains more than
* cRowsMax rows.
*/
STDAPI
HrQueryAllRows(LPMAPITABLE ptable,
LPSPropTagArray ptaga, LPSRestriction pres, LPSSortOrderSet psos,
LONG crowsMax, LPSRowSet FAR *pprows)
{
HRESULT hr;
LPSRowSet prows = NULL;
UINT crows = 0;
LPSRowSet prowsT;
UINT crowsT;
#if !defined(DOS)
// Why have we commented out the check for PARAMETER_VALIDATION? --gfb
//#ifdef PARAMETER_VALIDATION
if (FBadUnknown(ptable))
{
DebugTraceArg(HrQueryAllRows, TEXT("ptable fails address check"));
goto badArg;
}
if (ptaga && FBadColumnSet(ptaga))
{
DebugTraceArg(HrQueryAllRows, TEXT("ptaga fails address check"));
goto badArg;
}
if (pres && FBadRestriction(pres))
{
DebugTraceArg(HrQueryAllRows, TEXT("pres fails address check"));
goto badArg;
}
if (psos && FBadSortOrderSet(psos))
{
DebugTraceArg(HrQueryAllRows, TEXT("psos fails address check"));
goto badArg;
}
if (IsBadWritePtr(pprows, sizeof(LPSRowSet)))
{
DebugTraceArg(HrQueryAllRows, TEXT("pprows fails address check"));
goto badArg;
}
//#endif
#endif
*pprows = NULL;
// Set up the table, if the corresponding setup parameter
// is present.
if (ptaga &&
HR_FAILED(hr = ptable->lpVtbl->SetColumns(ptable, ptaga, TBL_BATCH)))
goto ret;
if (pres &&
HR_FAILED(hr = ptable->lpVtbl->Restrict(ptable, pres, TBL_BATCH)))
goto ret;
if (psos &&
HR_FAILED(hr = ptable->lpVtbl->SortTable(ptable, psos, TBL_BATCH)))
goto ret;
// Set position to beginning of the table.
if (HR_FAILED(hr = ptable->lpVtbl->SeekRow(ptable, BOOKMARK_BEGINNING,
0, NULL)))
goto ret;
if (crowsMax == 0)
crowsMax = LONG_MAX;
for (;;)
{
prowsT = NULL;
// Retrieve some rows. Ask for the limit.
hr = ptable->lpVtbl->QueryRows(ptable, crowsMax, 0, &prowsT);
if (HR_FAILED(hr))
{
// Note: the failure may actually have happened during
// one of the setup calls, since we set TBL_BATCH.
goto ret;
}
Assert(prowsT->cRows <= UINT_MAX);
crowsT = (UINT) prowsT->cRows;
// Did we get more rows than caller can handle?
if ((LONG) (crowsT + (prows ? prows->cRows : 0)) > crowsMax)
{
hr = ResultFromScode(MAPI_E_TABLE_TOO_BIG);
FreeProws(prowsT);
goto ret;
}
// Add the rows just retrieved into the set we're building.
// Note: this handles boundary conditions including either
// row set is empty.
if (HR_FAILED(hr = HrMergeRowSets(prowsT, &prows)))
goto ret;
// NOTE: the merge destroys prowsT.
// Did we hit the end of the table?
// Unfortunately, we have to ask twice before we know.
if (crowsT == 0)
break;
}
*pprows = prows;
ret:
if (HR_FAILED(hr))
FreeProws(prows);
DebugTraceResult(HrGetAllRows, hr);
return hr;
#if !defined(DOS)
badArg:
#endif
return ResultFromScode(MAPI_E_INVALID_PARAMETER);
}
#ifdef WIN16 // Imported inline function
/*
* IListedPropID
*
* Purpose
* If a tag with ID == PROP_ID(ulPropTag) is listed in lptaga then
* the index of tag is returned. If the tag is not in lptaga then
* -1 is returned.
*
* Arguments
* ulPropTag Property tag to locate.
* lptaga Property tag array to search.
*
* Returns TRUE or FALSE
*/
LONG
IListedPropID( ULONG ulPropTag,
LPSPropTagArray lptaga)
{
ULONG FAR *lpulPTag;
/* No tag is contained in a NULL list of tags.
*/
if (!lptaga)
{
return -1;
}
/* Mutate ulPropTag to just a PROP_ID.
*/
ulPropTag = PROP_ID(ulPropTag);
for ( lpulPTag = lptaga->aulPropTag + lptaga->cValues
; --lpulPTag >= lptaga->aulPropTag
; )
{
/* Compare PROP_ID's.
*/
if (PROP_ID(*lpulPTag) == ulPropTag)
{
return (lpulPTag - lptaga->aulPropTag);
}
}
return -1;
}
/*
* FListedPropID
*
* Purpose
* Determine if a tag with ID == PROP_ID(ulPropTag) is listed in lptaga.
*
* Arguments
* ulPropTag Property tag to locate.
* lptaga Property tag array to search.
*
* Returns TRUE or FALSE
*/
BOOL
FListedPropID( ULONG ulPropTag,
LPSPropTagArray lptaga)
{
ULONG FAR *lpulPTag;
/* No tag is contained in a NULL list of tags.
*/
if (!lptaga)
{
return FALSE;
}
/* Mutate ulPropTag to just a PROP_ID.
*/
ulPropTag = PROP_ID(ulPropTag);
for ( lpulPTag = lptaga->aulPropTag + lptaga->cValues
; --lpulPTag >= lptaga->aulPropTag
; )
{
/* Compare PROP_ID's.
*/
if (PROP_ID(*lpulPTag) == ulPropTag)
{
return TRUE;
}
}
return FALSE;
}
/*
* FListedPropTAG
*
* Purpose
* Determine if a the given ulPropTag is listed in lptaga.
*
* Arguments
* ulPropTag Property tag to locate.
* lptaga Property tag array to search.
*
* Returns TRUE or FALSE
*/
BOOL
FListedPropTAG( ULONG ulPropTag,
LPSPropTagArray lptaga)
{
ULONG FAR *lpulPTag;
/* No tag is contained in a NULL list of tags.
*/
if (!lptaga)
{
return FALSE;
}
/* Compare the entire prop tag to be sure both ID and TYPE match
*/
for ( lpulPTag = lptaga->aulPropTag + lptaga->cValues
; --lpulPTag >= lptaga->aulPropTag
; )
{
/* Compare PROP_ID's.
*/
if (PROP_ID(*lpulPTag) == ulPropTag)
{
return TRUE;
}
}
return FALSE;
}
/*
* AddProblem
*
* Purpose
* Adds a problem to the next available entry of a pre-allocated problem
* array.
* The pre-allocated problem array must be big enough to have another
* problem added. The caller is responsible for making sure this is
* true.
*
* Arguments
* lpProblems Pointer to pre-allocated probelem array.
* ulIndex Index into prop tag/value array of the problem property.
* ulPropTag Prop tag of property which had the problem.
* scode Error code to list for the property.
*
* Returns TRUE or FALSE
*/
VOID
AddProblem( LPSPropProblemArray lpProblems,
ULONG ulIndex,
ULONG ulPropTag,
SCODE scode)
{
if (lpProblems)
{
Assert( !IsBadWritePtr( lpProblems->aProblem + lpProblems->cProblem
, sizeof(SPropProblem)));
lpProblems->aProblem[lpProblems->cProblem].ulIndex = ulIndex;
lpProblems->aProblem[lpProblems->cProblem].ulPropTag = ulPropTag;
lpProblems->aProblem[lpProblems->cProblem].scode = scode;
lpProblems->cProblem++;
}
}
BOOL
FIsExcludedIID( LPCIID lpiidToCheck, LPCIID rgiidExclude, ULONG ciidExclude)
{
/* Check the obvious (no exclusions).
*/
if (!ciidExclude || !rgiidExclude)
{
return FALSE;
}
/* Check each iid in the list of exclusions.
*/
for (; ciidExclude; rgiidExclude++, ciidExclude--)
{
// if (IsEqualGUID( lpiidToCheck, rgiidExclude))
if (!memcmp( lpiidToCheck, rgiidExclude, sizeof(MAPIUID)))
{
return TRUE;
}
}
return FALSE;
}
/*
* Error/Warning Alert Message Boxes
*/
int AlertIdsCtx( HWND hwnd,
HINSTANCE hinst,
UINT idsMsg,
LPSTR szComponent,
ULONG ulContext,
ULONG ulLow,
UINT fuStyle);
int
AlertIds(HWND hwnd, HINSTANCE hinst, UINT idsMsg, UINT fuStyle)
{
return AlertIdsCtx(hwnd, hinst, idsMsg, NULL, 0, 0, fuStyle);
}
int AlertSzCtx( HWND hwnd,
LPSTR szMsg,
LPSTR szComponent,
ULONG ulContext,
ULONG ulLow,
UINT fuStyle);
int
AlertSz(HWND hwnd, LPSTR szMsg, UINT fuStyle)
{
return AlertSzCtx(hwnd, szMsg, NULL, 0, 0, fuStyle);
}
#endif // WIN16