ABCTBL2.C
资源名称:MSDN_VC98.zip [点击查看]
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:35k
源码类别:
Windows编程
开发平台:
Visual C++
- /***********************************************************************
- *
- * ABCTBL2.C
- *
- * Contents Table - Part 2.
- *
- *
- * The following routines are implemented in this file.
- *
- *
- * IVTABC_SeekRow
- * IVTABC_SeekRowApprox
- * IVTABC_GetRowCount
- * IVTABC_QueryPosition
- * IVTABC_FindRow
- * IVTABC_Restrict
- * IVTABC_QueryRows
- *
- *
- *
- * Copyright 1992-1995 Microsoft Corporation. All Rights Reserved.
- *
- ***********************************************************************/
- #include "abp.h"
- #include "abctbl.h"
- #include "sampabp.rh"
- /*************************************************************************
- *
- - IVTABC_SeekRow
- -
- *
- * Tries to seek an appropriate number of rows.
- *
- *
- */
- STDMETHODIMP
- IVTABC_SeekRow(LPIVTABC lpIVTAbc,
- BOOKMARK bkOrigin,
- LONG lRowCount,
- LONG * lplRowsSought)
- {
- LONG lNewPos;
- LONG lMoved;
- LONG lDelta;
- LONG lLast;
- HRESULT hResult = hrSuccess;
- /*
- * Validate parameters
- */
- IVTABC_ValidateObject(SeekRow, lpIVTAbc);
- Validate_IMAPITable_SeekRow(lpIVTAbc, bkOrigin, lRowCount, lplRowsSought);
- EnterCriticalSection(&lpIVTAbc->cs);
- if (bkOrigin == BOOKMARK_BEGINNING)
- {
- lNewPos = 0;
- }
- else if (bkOrigin == BOOKMARK_CURRENT)
- {
- lNewPos = lpIVTAbc->ulPosition;
- }
- else if (bkOrigin == BOOKMARK_END)
- {
- lNewPos = lpIVTAbc->ulMaxPos;
- }
- else
- {
- ULONG ulBK = (ULONG) bkOrigin - 3;
- LPABCBK lpABCBK = NULL;
- /*
- * See if it's out of range
- */
- if (ulBK < 0 || ulBK >= MAX_BOOKMARKS)
- {
- /*
- * bad book mark, it's an error, so...
- */
- hResult = ResultFromScode(E_INVALIDARG);
- goto out;
- }
- if (!(lpABCBK = lpIVTAbc->rglpABCBK[ulBK]))
- {
- /*
- * bookmark has not been allocated
- */
- hResult = ResultFromScode(MAPI_E_INVALID_BOOKMARK);
- goto out;
- }
- /* Not validating existing bookmark */
- lNewPos = lpABCBK->ulPosition;
- }
- /*
- * Figure out what endpoint to use and what direction to go to
- * get there.
- */
- if (lRowCount < 0)
- {
- lLast = 0;
- lDelta = -1;
- }
- else
- {
- lLast = lpIVTAbc->ulMaxPos;
- lDelta = 1;
- }
- /*
- * While there's rows to seek ...
- */
- lMoved = 0;
- while (lNewPos != lLast &&
- lMoved != lRowCount)
- {
- lNewPos += lDelta;
- /*
- * Unrestricted list is easy: just seek. Also, if the next
- * 'row' is the end of the table, just go there; don't want
- * to check it against any restriction.
- */
- if (!lpIVTAbc->lpszPartialName ||
- lNewPos == (LONG) lpIVTAbc->ulMaxPos)
- {
- lMoved += lDelta;
- }
- /*
- * Otherwise, deal with the restricted list: only count
- * the row if it's in the restriction.
- */
- else
- {
- if (!FChecked(lpIVTAbc, (ULONG) lNewPos))
- {
- hResult = HrValidateEntry(lpIVTAbc, (ULONG) lNewPos);
- if (HR_FAILED(hResult))
- {
- goto out;
- }
- }
- if (FMatched(lpIVTAbc, (ULONG) lNewPos))
- {
- lMoved += lDelta;
- }
- }
- }
- if (lplRowsSought)
- *lplRowsSought = lMoved;
- lpIVTAbc->ulPosition = lNewPos;
- out:
- LeaveCriticalSection(&lpIVTAbc->cs);
- DebugTraceResult(IVTABC_SeekRow, hResult);
- return hResult;
- }
- /*************************************************************************
- *
- - IVTABC_SeekRowApprox
- -
- * Tries to set the position of the table according to the approximate
- * position passed in.
- *
- *
- */
- STDMETHODIMP
- IVTABC_SeekRowApprox(LPIVTABC lpIVTAbc,
- ULONG ulNumerator,
- ULONG ulDenominator)
- {
- HRESULT hResult = hrSuccess;
- ULONG iByte;
- BYTE bCount;
- ULONG ulPos = 0;
- ULONG ulCount = 0;
- /*
- * Validate parameters
- */
- IVTABC_ValidateObject(SeekRowApprox, lpIVTAbc);
- Validate_IMAPITable_SeekRowApprox(lpIVTAbc, ulNumerator, ulDenominator);
- EnterCriticalSection(&lpIVTAbc->cs);
- if (ulNumerator >= ulDenominator)
- {
- /* We're at the end of the list */
- lpIVTAbc->ulPosition = lpIVTAbc->ulMaxPos;
- hResult = hrSuccess;
- goto out;
- }
- /*
- * Since I'm using muldiv() which takes ints/longs, I should shift right
- * so that I don't incorrectly call it.
- * I'm really just checking to see if the sign bit is set...
- */
- if (((long)ulNumerator < 0) || ((long)ulDenominator < 0))
- {
- ulNumerator >>= 1;
- ulDenominator >>= 1;
- }
- if (!lpIVTAbc->lpszPartialName)
- {
- /*
- * The NON-Restriction method
- */
- lpIVTAbc->ulPosition = MULDIV(lpIVTAbc->ulMaxPos, ulNumerator,
- ulDenominator);
- hResult = hrSuccess;
- goto out;
- }
- /*
- * Restriction method
- */
- /* Figure out % of which corresponds with numerator. */
- ulCount = MULDIV(lpIVTAbc->ulRstrDenom, ulNumerator, ulDenominator);
- /* Count bits in rgMatched until I match numerator */
- for (iByte = 0; iByte < (lpIVTAbc->ulMaxPos / 8); iByte++)
- {
- CBitsB(lpIVTAbc->rgMatched[iByte], bCount); /* <-- MACRO */
- ulPos += (ULONG) bCount;
- if (ulPos >= ulCount)
- {
- ulPos -= bCount; /* Go back a byte */
- break;
- }
- }
- /* My current position is there. */
- lpIVTAbc->ulPosition = iByte * 8;
- out:
- LeaveCriticalSection(&lpIVTAbc->cs);
- DebugTraceResult(IVTABC_SeekRowApprox, hResult);
- return hResult;
- }
- /*************************************************************************
- *
- - IVTABC_GetRowCount
- -
- *
- * If there's a restriction applied, I don't necessarily know how many
- * rows there are...
- */
- STDMETHODIMP
- IVTABC_GetRowCount(LPIVTABC lpIVTAbc,
- ULONG ulFlags,
- ULONG * lpulCount)
- {
- HRESULT hResult;
- /*
- * Validate parameters
- */
- IVTABC_ValidateObject(GetRowCount, lpIVTAbc);
- Validate_IMAPITable_GetRowCount(lpIVTAbc, ulFlags, lpulCount);
- EnterCriticalSection(&lpIVTAbc->cs);
- /*
- * If there's no restriction, you can actually calculate this..
- */
- if (!lpIVTAbc->lpszPartialName)
- {
- /*
- * Number of actual rows
- */
- *lpulCount = lpIVTAbc->ulMaxPos;
- hResult = hrSuccess;
- goto out;
- }
- /*
- * There's no way that I can tell how many actual entries there
- * are without counting them. That takes way too long, so we give
- * the client our best guess.
- */
- *lpulCount = lpIVTAbc->ulRstrDenom;
- /*
- * Then we warn the client that this count may not be accurate
- */
- hResult = ResultFromScode(MAPI_W_APPROX_COUNT);
- out:
- LeaveCriticalSection(&lpIVTAbc->cs);
- DebugTraceResult(IVTABC_GetRowCount, hResult);
- return hResult;
- }
- /*************************************************************************
- *
- - IVTABC_QueryPosition
- -
- * Figures out the current fractional position
- *
- *
- *
- */
- STDMETHODIMP
- IVTABC_QueryPosition(LPIVTABC lpIVTAbc,
- ULONG * lpulRow,
- ULONG * lpulNumerator,
- ULONG * lpulDenominator)
- {
- HRESULT hResult = hrSuccess;
- /*
- * Validate parameters
- */
- IVTABC_ValidateObject(QueryPosition, lpIVTAbc);
- Validate_IMAPITable_QueryPosition(lpIVTAbc, lpulRow, lpulNumerator,
- lpulDenominator);
- EnterCriticalSection(&lpIVTAbc->cs);
- /* ...I don't have a restriction */
- if (!lpIVTAbc->lpszPartialName)
- {
- *lpulRow = lpIVTAbc->ulPosition;
- *lpulNumerator = lpIVTAbc->ulPosition;
- *lpulDenominator = lpIVTAbc->ulMaxPos;
- }
- else
- {
- BYTE bCount = 0;
- BYTE bFrag;
- ULONG iByte;
- /*
- * Zero out fraction
- */
- *lpulNumerator = 0;
- /*
- * Set denominator that we've been keeping track of.
- */
- *lpulDenominator = (lpIVTAbc->ulRstrDenom ? lpIVTAbc->ulRstrDenom : 1);
- /*
- * Handle corner case - we're at the beginning of the list...
- */
- if (lpIVTAbc->ulPosition == 0)
- {
- *lpulRow = 0;
- goto out;
- }
- /*
- * Calculate Numerator
- * We use the rgMatched bit array and count the bits up to
- * our current position (lpIVTAbc->ulPosition).
- *
- */
- for (iByte = 0; iByte < (lpIVTAbc->ulPosition / 8); iByte++)
- {
- CBitsB(lpIVTAbc->rgMatched[iByte], bCount); /* <-- MACRO */
- *lpulNumerator += (ULONG) bCount;
- }
- /* Count the fragment */
- bFrag = lpIVTAbc->rgMatched[iByte];
- bFrag = bFrag >> (8 - (lpIVTAbc->ulPosition % 8));
- CBitsB(bFrag, bCount);
- *lpulNumerator += (ULONG) bCount;
- /*
- * Good guess here...
- */
- *lpulRow = *lpulNumerator;
- }
- out:
- LeaveCriticalSection(&lpIVTAbc->cs);
- DebugTraceResult(IVTABC_QueryPosition, hResult);
- return hResult;
- }
- /*************************************************************************
- *
- - IVTABC_FindRow
- -
- *
- * Prefix searches to find a row
- *
- *
- */
- STDMETHODIMP
- IVTABC_FindRow(LPIVTABC lpIVTAbc,
- LPSRestriction lpRestriction,
- BOOKMARK bkOrigin,
- ULONG ulFlags)
- {
- HRESULT hResult = hrSuccess;
- ULONG cbRead;
- ABCREC abcrec;
- LONG lpos;
- ULONG fFound = FALSE;
- LPSTR szPrefix;
- int nCmpResult;
- ULONG ulCurMin;
- ULONG ulCurMac;
- ULONG ulPosT;
- /*
- * Validate parameters
- */
- IVTABC_ValidateObject(FindRow, lpIVTAbc);
- Validate_IMAPITable_FindRow(lpIVTAbc, lpRestriction, bkOrigin, ulFlags);
- /*
- * I don't go backwards, yet.
- */
- if (ulFlags & DIR_BACKWARD)
- {
- hResult = ResultFromScode(MAPI_E_NO_SUPPORT);
- DebugTraceResult(IVTABC_FindRow, hResult);
- return hResult;
- }
- EnterCriticalSection(&lpIVTAbc->cs);
- /*
- * Open the file
- */
- hResult = HrOpenFile(lpIVTAbc);
- if (HR_FAILED(hResult))
- {
- goto out;
- }
- /*
- * initialize
- */
- ulCurMin = lpIVTAbc->ulPosition;
- ulCurMac = lpIVTAbc->ulMaxPos;
- /*
- * I handle two type of restrictions:
- * prefix searching on Display Names
- * Finding a row based on it's instance key
- */
- /*
- * The prefix search on display name restriction looks like:
- *
- * +-----------------
- * | RES_PROPERTY
- * +-----------------
- * | RELOP_GE
- * +-----------------
- * | PR_DISPLAY_NAME
- * +-----------------
- * | LPSPropVal -----+
- * +----------------- |
- * | +-------------------------
- * +-->| PR_DISPLAY_NAME
- * +-------------------------
- * | 0 <-- for alignment (don't care)
- * +-------------------------
- * | lpszA <-- prefix for display name
- * +-------------------------
- *
- *
- *
- * -OR-
- *
- * Find a row based on it's instance key
- *
- * +-----------------
- * | RES_PROPERTY
- * +-----------------
- * | RELOP_EQ
- * +-----------------
- * | PR_INSTANCE_KEY
- * +-----------------
- * | LPSPropVal -----+
- * +----------------- |
- * | +-------------------------
- * +-->| PR_INSTANCE_KEY
- * +-------------------------
- * | | cbInstanceKey
- * + bin +-------------------
- * | | lpbInstanceKey
- * +-------------------------
- *
- *
- * If it doesn't look like one of these, return MAPI_E_TOO_COMPLEX.
- */
- /*
- * Both restrictions require this one
- */
- if (lpRestriction->rt != RES_PROPERTY)
- {
- hResult = ResultFromScode(MAPI_E_TOO_COMPLEX);
- goto out;
- }
- /*
- * Look for Instance Key first - it's easiest to handle
- */
- if (lpRestriction->res.resProperty.relop == RELOP_EQ)
- {
- LPABCRecInstance lpABCRecInstance;
- if (lpRestriction->res.resProperty.ulPropTag != PR_INSTANCE_KEY)
- {
- /*
- * Clearly something we don't recognize
- */
- hResult = ResultFromScode(MAPI_E_TOO_COMPLEX);
- goto out;
- }
- /*
- * Crack the bin part of this restriction and
- * see if we can still find our way back to this
- * record - quickly...
- */
- lpABCRecInstance = (LPABCRecInstance) lpRestriction->res.resProperty.lpProp->Value.bin.lpb;
- /*
- * First check to see that we're browsing the same file
- */
- if (lstrcmp(lpABCRecInstance->rgchzFileName, lpIVTAbc->lpszFileName))
- {
- /*
- * Nope, different names, return not found and leave our position alone...
- */
- hResult = ResultFromScode(MAPI_E_NOT_FOUND);
- goto out;
- }
- /*
- * Ok, so we think we're browsing the same file. Has it been modified since the
- * last time we looked?
- */
- if (memcmp(&(lpABCRecInstance->filetime), &(lpIVTAbc->filetime), sizeof (FILETIME)))
- {
- /*
- * Nope, they're different, so no guarantees here...
- */
- hResult = ResultFromScode(MAPI_E_NOT_FOUND);
- goto out;
- }
- /*
- * Now, I feel pretty confident about this instance key. Just set my current position
- * and go for it.
- */
- lpIVTAbc->ulPosition = lpABCRecInstance->ulRecordPosition;
- /* Done */
- goto out;
- }
- /*
- * Now we're looking for prefix searching on display name
- */
- if (lpRestriction->res.resProperty.relop != RELOP_GE)
- {
- hResult = ResultFromScode(MAPI_E_TOO_COMPLEX);
- goto out;
- }
- if (lpRestriction->res.resProperty.ulPropTag != PR_DISPLAY_NAME_A)
- {
- hResult = ResultFromScode(MAPI_E_TOO_COMPLEX);
- goto out;
- }
- szPrefix = lpRestriction->res.resProperty.lpProp->Value.lpszA;
- if (bkOrigin == BOOKMARK_BEGINNING)
- {
- ulCurMin = 0;
- }
- else if (bkOrigin == BOOKMARK_END)
- {
- ulCurMin = lpIVTAbc->ulMaxPos;
- }
- else if (bkOrigin != BOOKMARK_CURRENT)
- {
- ULONG ulBK = (ULONG) bkOrigin - 3;
- LPABCBK lpABCBK = NULL;
- /*
- * See if it's out of range
- */
- if (ulBK < 0 || ulBK >= MAX_BOOKMARKS)
- {
- /*
- * bad book mark, it's an error, so...
- */
- hResult = ResultFromScode(E_INVALIDARG);
- goto out;
- }
- if (!(lpABCBK = lpIVTAbc->rglpABCBK[ulBK]))
- {
- /*
- * bookmark has not been allocated
- */
- hResult = ResultFromScode(MAPI_E_INVALID_BOOKMARK);
- goto out;
- }
- /* Not validating existing bookmark */
- ulCurMin = lpABCBK->ulPosition;
- }
- while (ulCurMin < ulCurMac)
- {
- /*
- * Look for a row which matches the table restriction (if any).
- */
- ulPosT = (ulCurMin + ulCurMac) / 2;
- lpos = (long)((long)ulPosT * (long)sizeof(ABCREC));
- SetFilePointer(lpIVTAbc->hFile, lpos, NULL, FILE_BEGIN);
- /* Read in the record at that location */
- if (!ReadFile(lpIVTAbc->hFile, (LPVOID) &abcrec,
- sizeof(ABCREC), &cbRead, NULL))
- {
- hResult = ResultFromScode(MAPI_E_DISK_ERROR);
- SetErrorIDS(lpIVTAbc, hResult, IDS_SAB_NO_READ);
- goto out;
- }
- /*
- * I want case insensitive comparisons here...
- */
- nCmpResult = lstrcmpi(szPrefix, abcrec.rgchDisplayName);
- if (nCmpResult > 0)
- {
- ulCurMin = ulPosT + 1;
- }
- else
- {
- ulCurMac = ulPosT;
- if (!lpIVTAbc->lpszPartialName ||
- FNameMatch(lpIVTAbc, abcrec.rgchDisplayName))
- {
- fFound = TRUE;
- }
- }
- }
- /*
- * If I didn't find a row, return MAPI_E_NOT_FOUND.
- */
- if (!fFound)
- {
- hResult = ResultFromScode(MAPI_E_NOT_FOUND);
- goto out;
- }
- /*
- * Otherwise, set the current position to the row found.
- */
- lpIVTAbc->ulPosition = ulCurMac;
- out:
- LeaveCriticalSection(&lpIVTAbc->cs);
- DebugTraceResult(IVTABC_FindRow, hResult);
- return hResult;
- }
- /*************************************************************************
- *
- - IVTABC_Restrict
- -
- *
- * Should just support ANR type restrictions...
- */
- STDMETHODIMP
- IVTABC_Restrict(LPIVTABC lpIVTAbc,
- LPSRestriction lpRestriction,
- ULONG ulFlags)
- {
- LPSTR szT = NULL;
- LPSTR lpszTNew = NULL;
- ULONG cbTB = 0;
- BYTE bFilter = 0;
- SCODE scode;
- HRESULT hResult = hrSuccess;
- /*
- * Validate parameters
- */
- IVTABC_ValidateObject(Restrict, lpIVTAbc);
- Validate_IMAPITable_Restrict(lpIVTAbc, lpRestriction, ulFlags);
- /*
- * I only handle ANR type restrictions
- */
- /*
- * Check to see if they're resetting the restrictions
- */
- if (!lpRestriction)
- {
- EnterCriticalSection(&lpIVTAbc->cs);
- if (lpIVTAbc->lpszPartialName)
- (*(lpIVTAbc->lpFreeBuff)) (lpIVTAbc->lpszPartialName);
- lpIVTAbc->lpszPartialName = NULL;
- FreeANRBitmaps(lpIVTAbc);
- LeaveCriticalSection(&lpIVTAbc->cs);
- return hrSuccess;
- }
- /*
- * The restriction must look like:
- *
- *
- * +--------------
- * | RES_PROPERTY
- * +--------------
- * | RELOP_EQ
- * +--------------
- * | PR_ANR
- * +--------------
- * | LPSPropVal ---+
- * +-------------- |
- * | +-------------------------
- * +-->| PR_ANR
- * +-------------------------
- * | 0 <-- for alignment (don't care)
- * +-------------------------
- * | lpszA <-- string to ANR on
- * +-------------------------
- *
- *
- *
- * If it doesn't look like this, return MAPI_E_TOO_COMPLEX.
- *
- */
- if (lpRestriction->rt != RES_PROPERTY)
- {
- hResult = ResultFromScode(MAPI_E_TOO_COMPLEX);
- goto out;
- }
- if (lpRestriction->res.resProperty.relop != RELOP_EQ)
- {
- hResult = ResultFromScode(MAPI_E_TOO_COMPLEX);
- goto out;
- }
- if (lpRestriction->res.resProperty.ulPropTag != PR_ANR)
- {
- hResult = ResultFromScode(MAPI_E_TOO_COMPLEX);
- goto out;
- }
- /*
- * NULL string is not defined - it's a bad restriction
- */
- if (!lpRestriction->res.resProperty.lpProp->Value.lpszA)
- {
- hResult = ResultFromScode(E_INVALIDARG);
- goto out;
- }
- szT = lpRestriction->res.resProperty.lpProp->Value.lpszA;
- /*
- * Skip over leading spaces
- */
- while (*szT == ' ')
- szT++;
- /*
- * Empty string is not defined - it's a bad restriction
- */
- if (*szT == ' ')
- {
- hResult = ResultFromScode(E_INVALIDARG);
- goto out;
- }
- /*
- * Copy the string for the partial name
- */
- scode = lpIVTAbc->lpAllocBuff(lstrlenA(szT) + 1, (LPVOID *) &lpszTNew);
- if (FAILED(scode))
- {
- /*
- * Memory error
- */
- hResult = ResultFromScode(scode);
- goto out;
- }
- lstrcpyA(lpszTNew, szT);
- EnterCriticalSection(&lpIVTAbc->cs);
- /*
- * Clear up any old restriction
- */
- if (lpIVTAbc->lpszPartialName)
- lpIVTAbc->lpFreeBuff(lpIVTAbc->lpszPartialName);
- lpIVTAbc->lpszPartialName = lpszTNew;
- FreeANRBitmaps(lpIVTAbc);
- /*
- * Allocate enough bits for the checked&matched arrays
- */
- cbTB = (lpIVTAbc->ulMaxPos) / 8 + 1; /* Number of bytes in both arrays */
- lpIVTAbc->rgChecked = lpIVTAbc->lpMalloc->lpVtbl->Alloc(
- lpIVTAbc->lpMalloc,
- cbTB);
- if (lpIVTAbc->rgChecked == NULL)
- {
- lpIVTAbc->lpFreeBuff(lpIVTAbc->lpszPartialName);
- lpIVTAbc->lpszPartialName = NULL;
- hResult = ResultFromScode(scode);
- LeaveCriticalSection(&lpIVTAbc->cs);
- goto out;
- }
- lpIVTAbc->rgMatched = lpIVTAbc->lpMalloc->lpVtbl->Alloc(
- lpIVTAbc->lpMalloc,
- cbTB);
- if (lpIVTAbc->rgMatched == NULL)
- {
- (*(lpIVTAbc->lpFreeBuff)) (lpIVTAbc->lpszPartialName);
- lpIVTAbc->lpszPartialName = NULL;
- lpIVTAbc->lpMalloc->lpVtbl->Free(lpIVTAbc->lpMalloc, lpIVTAbc->rgChecked);
- lpIVTAbc->rgChecked = NULL;
- hResult = ResultFromScode(scode);
- LeaveCriticalSection(&lpIVTAbc->cs);
- goto out;
- }
- /*
- * Initialize the checked array with 0's
- */
- FillMemory(lpIVTAbc->rgChecked, (UINT) cbTB, 0x00);
- /*
- * Initialize the matched array with 1's
- * [we assume that if you haven't checked it, it matches]
- */
- FillMemory(lpIVTAbc->rgMatched, (UINT) cbTB, 0xFF);
- /*
- * Fill in the end bits so we don't have to worry about them
- * later
- */
- bFilter = (0xFF >> (lpIVTAbc->ulMaxPos % 8));
- /* Checked end bits should be 1 */
- lpIVTAbc->rgChecked[cbTB - 1] = bFilter;
- /* Matched end bits should be 0 */
- lpIVTAbc->rgMatched[cbTB - 1] = ~bFilter;
- /*
- * Set the currenly known total number of rows
- * that match the restriction.
- */
- lpIVTAbc->ulRstrDenom = lpIVTAbc->ulMaxPos;
- LeaveCriticalSection(&lpIVTAbc->cs);
- out:
- DebugTraceResult(IVTABC_Restrict, hResult);
- return hResult;
- }
- /*************************************************************************
- *
- - IVTABC_QueryRows
- -
- * Attempts to retrieve ulRowCount rows from the .SAB file. Even in the
- * restricted case.
- *
- *
- */
- STDMETHODIMP
- IVTABC_QueryRows(LPIVTABC lpIVTAbc,
- LONG lRowCount,
- ULONG ulFlags,
- LPSRowSet * lppRows)
- {
- SCODE scode;
- HRESULT hResult = hrSuccess;
- LPSRowSet lpRowSet = NULL;
- LPSPropValue lpRow = NULL;
- int cbSizeOfRow;
- int cRows, iRow;
- int cCols;
- DWORD cbRead;
- ABCREC abcrec;
- ULONG ulOrigPosition;
- /*
- * Validate parameters
- */
- IVTABC_ValidateObject(QueryRows, lpIVTAbc);
- Validate_IMAPITable_QueryRows(lpIVTAbc, lRowCount, ulFlags, lppRows);
- if (lRowCount < 0)
- {
- hResult = ResultFromScode(E_INVALIDARG);
- DebugTraceResult(IVTABC_QueryRows, hResult);
- return hResult;
- }
- /*
- * Check the flags
- */
- if (ulFlags & ~TBL_NOADVANCE)
- {
- hResult = ResultFromScode(MAPI_E_UNKNOWN_FLAGS);
- DebugTraceResult(IVTABC_QueryRows, hResult);
- return hResult;
- }
- EnterCriticalSection(&lpIVTAbc->cs);
- /*
- * Open the file
- */
- hResult = HrOpenFile(lpIVTAbc);
- if (HR_FAILED(hResult))
- {
- goto out;
- }
- ulOrigPosition = lpIVTAbc->ulPosition;
- /*
- * Calculate # of rows that will be read.
- */
- cRows = (int)lpIVTAbc->ulMaxPos - (int)lpIVTAbc->ulPosition;
- cRows = (cRows < (int)lRowCount ? cRows : (int)lRowCount);
- /*
- * Allocate array for SRowSet
- */
- scode = lpIVTAbc->lpAllocBuff(sizeof(ULONG) + cRows * sizeof(SRow),
- (LPVOID *) &lpRowSet);
- if (FAILED(scode))
- {
- hResult = ResultFromScode(scode);
- goto out;
- }
- /*
- * Initialize - so we can clean up later if we have to...
- */
- lpRowSet->cRows = cRows;
- for (iRow = 0; iRow < cRows; iRow++)
- lpRowSet->aRow[iRow].lpProps = NULL;
- /*
- * Seek to correct position in file
- */
- (void) SetFilePointer(lpIVTAbc->hFile, lpIVTAbc->ulPosition * sizeof(ABCREC),
- NULL, FILE_BEGIN);
- /*
- * Read each row from the file
- */
- for (iRow = 0; iRow < cRows; iRow++)
- {
- /* The only properties available are:
- *
- * PR_DISPLAY_NAME, PR_ENTRYID, PR_ADDRTYPE, PR_EMAIL_ADDRESS,
- * PR_OBJECT_TYPE, PR_DISPLAY_TYPE
- */
- /*
- * Handle restricted lists
- */
- if (lpIVTAbc->lpszPartialName)
- {
- ULONG ulPos = lpIVTAbc->ulPosition;
- next:
- if (ulPos == lpIVTAbc->ulMaxPos)
- {
- break;
- }
- if (!FChecked(lpIVTAbc, ulPos))
- {
- hResult = HrValidateEntry(lpIVTAbc, ulPos);
- if (HR_FAILED(hResult))
- {
- goto err;
- }
- }
- if (!FMatched(lpIVTAbc, ulPos))
- {
- ulPos++;
- goto next;
- }
- lpIVTAbc->ulPosition = ulPos;
- (void) SetFilePointer(lpIVTAbc->hFile, lpIVTAbc->ulPosition * sizeof(ABCREC),
- NULL, FILE_BEGIN);
- }
- lpIVTAbc->ulPosition++;
- /*
- * Read in the record from the file
- */
- if (!ReadFile(lpIVTAbc->hFile, (LPVOID) &abcrec,
- sizeof(ABCREC), &cbRead, NULL))
- {
- hResult = ResultFromScode(MAPI_E_DISK_ERROR);
- SetErrorIDS(lpIVTAbc, hResult, IDS_SAB_NO_READ);
- goto err;
- }
- /* Second check */
- if ((UINT) cbRead != sizeof(ABCREC))
- {
- /*
- * Should never get here.
- */
- hResult = ResultFromScode(MAPI_E_DISK_ERROR);
- SetErrorIDS(lpIVTAbc, hResult, IDS_SAB_NO_READ);
- goto err;
- }
- /* Allocate memory to start a row.
- */
- cbSizeOfRow = sizeof(ULONG) +
- (int)lpIVTAbc->lpPTAColSet->cValues * sizeof(SPropValue);
- scode = lpIVTAbc->lpAllocBuff(cbSizeOfRow, (LPVOID *) &lpRow);
- if (FAILED(scode))
- {
- hResult = ResultFromScode(scode);
- goto err;
- }
- /*
- * Get all the data
- */
- for (cCols = 0; cCols < (int)lpIVTAbc->lpPTAColSet->cValues; cCols++)
- {
- switch (lpIVTAbc->lpPTAColSet->aulPropTag[cCols])
- {
- case PR_DISPLAY_NAME_A:
- {
- lpRow[cCols].ulPropTag = PR_DISPLAY_NAME_A;
- scode = lpIVTAbc->lpAllocMore (lstrlenA(abcrec.rgchDisplayName) + 1,
- lpRow,
- (LPVOID *) &(lpRow[cCols].Value.lpszA));
- if (FAILED(scode))
- {
- lpRow[cCols].ulPropTag = PROP_TAG(PT_ERROR,
- PROP_ID(PR_DISPLAY_NAME_A));
- lpRow[cCols].Value.err = scode;
- }
- else
- {
- lstrcpyA(lpRow[cCols].Value.lpszA,
- abcrec.rgchDisplayName);
- }
- }
- break;
- case PR_EMAIL_ADDRESS_A:
- {
- lpRow[cCols].ulPropTag = PR_EMAIL_ADDRESS_A;
- scode = lpIVTAbc->lpAllocMore (
- lstrlenA(abcrec.rgchEmailAddress) + 1,
- lpRow, (LPVOID *) &(lpRow[cCols].Value.lpszA));
- if (FAILED(scode))
- {
- lpRow[cCols].ulPropTag = PROP_TAG(PT_ERROR,
- PROP_ID(PR_EMAIL_ADDRESS_A));
- lpRow[cCols].Value.err = scode;
- }
- else
- {
- lstrcpyA(lpRow[cCols].Value.lpszA,
- abcrec.rgchEmailAddress);
- }
- }
- break;
- case PR_ADDRTYPE:
- {
- /*
- * AddrType is always "MSPEER" for the SAB
- */
- lpRow[cCols].ulPropTag = PR_ADDRTYPE_A;
- scode = lpIVTAbc->lpAllocMore (lstrlenA(lpszEMT) + 1,
- lpRow, (LPVOID *) &(lpRow[cCols].Value.lpszA));
- if (FAILED(scode))
- {
- lpRow[cCols].ulPropTag = PROP_TAG(PT_ERROR,
- PROP_ID(PR_ADDRTYPE_A));
- lpRow[cCols].Value.err = scode;
- }
- else
- {
- lstrcpyA(lpRow[cCols].Value.lpszA, lpszEMT);
- }
- }
- break;
- case PR_ENTRYID:
- {
- /*
- * Fixed sized entryid. Basically just the .SAB file record
- */
- LPUSR_ENTRYID lpUsrEid;
- lpRow[cCols].ulPropTag = PR_ENTRYID;
- scode = lpIVTAbc->lpAllocMore (sizeof(USR_ENTRYID), lpRow,
- (LPVOID *) &(lpRow[cCols].Value.bin.lpb));
- if (FAILED(scode))
- {
- lpRow[cCols].ulPropTag = PROP_TAG(PT_ERROR,
- PROP_ID(PR_ENTRYID));
- lpRow[cCols].Value.err = scode;
- }
- else
- {
- lpUsrEid = (LPUSR_ENTRYID) lpRow[cCols].Value.bin.lpb;
- ZeroMemory(lpUsrEid, sizeof(USR_ENTRYID));
- /* Size of entryid */
- lpRow[cCols].Value.bin.cb = sizeof(USR_ENTRYID);
- lpUsrEid->abFlags[0] = 0; /* long-term, recipient */
- lpUsrEid->abFlags[1] = 0;
- lpUsrEid->abFlags[2] = 0;
- lpUsrEid->abFlags[3] = 0;
- lpUsrEid->muid = muidABSample;
- lpUsrEid->ulVersion = SAMP_VERSION;
- lpUsrEid->ulType = SAMP_USER;
- lpUsrEid->abcrec = abcrec;
- }
- }
- break;
- case PR_OBJECT_TYPE:
- {
- /*
- * MailUser
- */
- lpRow[cCols].ulPropTag = PR_OBJECT_TYPE;
- lpRow[cCols].Value.ul = MAPI_MAILUSER;
- }
- break;
- case PR_DISPLAY_TYPE:
- {
- /*
- * MailUser
- */
- lpRow[cCols].ulPropTag = PR_DISPLAY_TYPE;
- lpRow[cCols].Value.ul = DT_MAILUSER;
- }
- break;
- case PR_INSTANCE_KEY:
- {
- LPABCRecInstance lpABCRecInstance;
- UINT cbRecInstance;
- /*
- * Instance keys are made up of:
- * ulRecordPosition - current position in the file
- * filetime - current date and time stamp of file
- * lpszFileName - current file that we're browsing
- */
- lpRow[cCols].ulPropTag = PR_INSTANCE_KEY;
- cbRecInstance = sizeof(ABCRecInstance)+lstrlen(lpIVTAbc->lpszFileName)+1;
- scode = lpIVTAbc->lpAllocMore(cbRecInstance,
- lpRow,
- (LPVOID) &(lpRow[cCols].Value.bin.lpb));
- if (FAILED(scode))
- {
- lpRow[cCols].ulPropTag = PROP_TAG(PT_ERROR,
- PROP_ID(PR_INSTANCE_KEY));
- lpRow[cCols].Value.err = scode;
- }
- else
- {
- lpABCRecInstance = (LPABCRecInstance) lpRow[cCols].Value.bin.lpb;
- ZeroMemory(lpABCRecInstance, cbRecInstance);
- lpRow[cCols].Value.bin.cb = (ULONG) cbRecInstance;
- lpABCRecInstance->ulRecordPosition = lpIVTAbc->ulPosition;
- lpABCRecInstance->filetime = lpIVTAbc->filetime;
- lstrcpy(lpABCRecInstance->rgchzFileName, lpIVTAbc->lpszFileName);
- }
- }
- break;
- default:
- {
- lpRow[cCols].ulPropTag = PROP_TAG(PT_ERROR,
- PROP_ID(lpIVTAbc->lpPTAColSet->aulPropTag[cCols]));
- lpRow[cCols].Value.err = MAPI_E_NOT_FOUND;
- }
- break;
- }
- }
- /* # of columns */
- lpRowSet->aRow[iRow].cValues = lpIVTAbc->lpPTAColSet->cValues;
- /* Actual row of data */
- lpRowSet->aRow[iRow].lpProps = lpRow;
- lpRow = NULL;
- }
- /*
- * it's always iRow.
- */
- lpRowSet->cRows = iRow;
- /*
- * Handle Seeked position stuff
- */
- if (ulFlags & TBL_NOADVANCE)
- {
- /*
- * Set it back to it's original position
- */
- lpIVTAbc->ulPosition = ulOrigPosition;
- }
- *lppRows = lpRowSet;
- out:
- LeaveCriticalSection(&lpIVTAbc->cs);
- DebugTraceResult(IVTABC_QueryRows, hResult);
- return hResult;
- err:
- /*
- * Clean up memory...
- */
- /* Free the row */
- lpIVTAbc->lpFreeBuff(lpRow);
- /* Clean up the rest of the rows */
- FreeProws(lpRowSet);
- *lppRows = NULL;
- goto out;
- }