|
|
/*
- MEMORY.C - * * Contains the following functions exported from MAPIX.DLL: * MAPIAllocateBuffer * MAPIAllocateMore * MAPIFreeBuffer * * Contains the following functions handed to providers: * MAPIAllocateBufferProv * MAPIAllocateMoreProv * * Contains the following functions private to MAPIX.DLL: * MAPIAllocateBufferExt * MAPIAllocateMoreExt */
#include "_apipch.h"
#define _MEMORY_C
// Critical section for serializing heap access
#if (defined(WIN32) || defined(WIN16)) && !defined(MAC)
CRITICAL_SECTION csHeap; #endif
#if (defined(WIN32) || defined(WIN16)) && !defined(MAC)
CRITICAL_SECTION csMapiInit; #endif
#if (defined(WIN32) || defined(WIN16)) && !defined(MAC)
CRITICAL_SECTION csMapiSearchPath; #endif
#ifdef WIN32
/* This is the entire 32-bit implementation for instance globals. */ VOID FAR *pinstX = NULL; #endif
#ifndef MAC
// DefineInstList(lpInstUtil);
#endif
#ifdef MAC
#include <utilmac.h>
#define PvGetInstanceGlobals() PvGetInstanceGlobalsMac(kInstMAPIX)
#define PvGetInstanceGlobalsEx(_x) PvGetInstanceGlobalsMac(kInstMAPIU)
#endif
// Buffer link overhead.
// Blocks of memory obtained with MAPIAllocateMore are linked to a
// block obtained with MAPIAllocateBuffer, so that the whole chain
// may be freed with one call to MAPIFreeBuffer.
typedef struct _BufInternal * LPBufInternal; typedef struct _BufInternal { #ifdef DEBUG
ULONG ulPad; HLH hHeap; #endif
ULONG ulAllocFlags; LPBufInternal pLink; } BufInternal;
// Values for ulAllocFlags. This dword contains two kinds of
// information:
// = In the high-order word, flags telling whether or not
// the block is the head of an allocation chain, and whether
// the block contains additional debugging information.
// = In the low-order word, an enum telling which heap
// it was allocated from.
#ifdef DEBUG
#define ALLOC_DEBUG ((ULONG) 0x40000000)
#else
#define ALLOC_DEBUG ((ULONG) 0x00000000)
#endif
#define ALLOC_WITH_ALLOC (((ULONG) 0x10000000) | ALLOC_DEBUG)
#define ALLOC_WITH_ALLOC_MORE (((ULONG) 0x20000000) | ALLOC_DEBUG)
#define FLAGSMASK ((ULONG) 0xFFFF0000)
#define GetFlags(_fl) ((ULONG) (_fl) & FLAGSMASK)
#define heapidClient 1
#define heapidProvider 2
#define HEAPIDMASK 0xFFFF
#define GetHeapid(_fl) (((int)(_fl)) & HEAPIDMASK)
// Conversion macros
#define INT_SIZE(a) ((a) + sizeof (BufInternal))
#define LPBufExtFromLPBufInt( PBUFINT ) \
((LPVOID)(((LPBYTE) PBUFINT) + sizeof(BufInternal)))
#define LPBufIntFromLPBufExt( PBUFEXT ) \
((LPBufInternal)(((LPBYTE) PBUFEXT) - sizeof(BufInternal)))
#ifdef DEBUG
// Internal stuff for checking memory buffer consistency.
// The flag fAssertBadBlocks governs whether we generate an
// assert or a debug trace when passed a bad block.
// By default, we'll assert.
// In the macros, _p is the address of a memory block;
// _s is a string describing what's wrong with it
static int fAssertBadBlocks = -1; // read from INI file
#define TellBadBlock(_p, _s) \
{ if (fAssertBadBlocks == 1) \ TrapSz1( TEXT("MAPIAlloc: memory block %08lX ") _s TEXT("\n"), _p); \ else \ TraceSz1( TEXT("MAPIAlloc: memory block %08lX ") _s TEXT("\n"), _p); } #define TellBadBlockInt(_p, _s) \
{ if (fAssertBadBlocks == 1) \ TrapSz1( TEXT("MAPIAlloc: memory block %08lX ") _s TEXT("\n"), LPBufExtFromLPBufInt(_p)); \ else \ TraceSz1( TEXT("MAPIAlloc: memory block %08lX ") _s TEXT("\n"), LPBufExtFromLPBufInt(_p)); }
BOOL FValidAllocChain(LPBufInternal lpBuf);
#else
#define TellBadBlock(_p, _s)
#define TellBadBlockInt(_p, _s)
#endif
/* Internal Prototypes */
STDMETHODIMP_(SCODE) MAPIAllocateBufferExt( int heapid, ULONG ulSize, LPVOID * lppv);
STDMETHODIMP_(SCODE) MAPIAllocateMoreExt( int heapid, ULONG ulSize, LPVOID lpv, LPVOID * lppv);
SCODE ScGetHlh(int heapid, HLH FAR *phlh);
#ifndef MAC
#ifndef WIN32
#pragma SEGMENT(MAPI_Core1)
#endif
#else
#pragma code_seg("mapi", "fixed")
#endif
/*----------------------------------------------*/ /* Beginning of Client Allocators */ /*----------------------------------------------*/
/*
* MAPIAllocateBuffer * * Purpose: * Allocates a memory buffer on behalf of the client. Can be * freed with MAPIFreeBuffer(). * * Arguments: * ulSize in Size, in bytes, of the buffer to be allocated. * lppv out Pointer to variable where the address of the * allocated memory will be returned. * * Assumes: * Should be called from a client and therefore will allocate * memory from the Client heap - pinst->hlhClient. * * Returns: * HRESULT: created from scodes described below. * * Side effects: * Increments allocation count in the INST. * * Errors: * MAPI_E_INSUFFICIENT_MEMORY Allocation failed. * MAPI_E_INVALID_PARAMETER Second argument is invalid. * MAPI_E_INVALID_PARAMETER ulSize is out of range (>= 65535 on Win16). */
STDMETHODIMP_(SCODE) MAPIAllocateBuffer(ULONG ulSize, LPVOID * lppv) { SCODE sc = S_OK;
if (lpfnAllocateBufferExternal) { return(lpfnAllocateBufferExternal(ulSize, lppv)); }
#ifdef DEBUG
// Initialize flag that controls how noisy we are about invalid
// blocks passed to us.
if (fAssertBadBlocks == -1) { fAssertBadBlocks = GetPrivateProfileInt( TEXT("General"), TEXT("AssertBadBlocks"), 1, TEXT("WABDBG.INI")); } #endif
#ifdef PARAMETER_VALIDATION
if (IsBadWritePtr((LPVOID) lppv, sizeof (LPVOID))) { DebugTraceArg(MAPIAllocateBuffer, TEXT("lppv fails address check")); return MAPI_E_INVALID_PARAMETER; } #endif
sc = MAPIAllocateBufferExt(heapidClient, ulSize, lppv);
DebugTraceSc(MAPIAllocateBuffer, sc); return sc; }
/*
* MAPIAllocateMore * * Purpose: * Allocates a linked memory buffer on behalf of the client, * in such a way that it can be freed with one call to MAPIFreeBuffer * (passing the buffer the client originally allocated with * MAPIAllocateBuffer). * * Arguments: * ulSize in Size, in bytes, of the buffer to be allocated. * lpv in Pointer to a buffer allocated with MAPIAllocateBuffer. * lppv out Pointer to variable where the address of the * allocated memory will be returned. * * Assumes: * Validates that lpBufOrig and lppv point to writable memory. * Validate that ulSize is less than 64K (on Win16 only) and that * lpBufOrig was allocated with MAPIAllocateBuffer. * Should be called from a client and therefore will allocate * memory from the Client heap - pinstUtil->hlhClient. * * Returns: * HRESULT: created from scodes described below. * * Side effects: * None * * Errors: * MAPI_E_INSUFFICIENT_MEMORY Allocation failed. * MAPI_E_INVALID_PARAMETER Second or third argument is invalid. * MAPI_E_INVALID_PARAMETER ulSize is out of range (>= 65535). */
STDMETHODIMP_(SCODE) MAPIAllocateMore(ULONG ulSize, LPVOID lpv, LPVOID * lppv) { SCODE sc = S_OK;
if (lpfnAllocateMoreExternal) { return(lpfnAllocateMoreExternal(ulSize, lpv, lppv)); }
#ifdef PARAMETER_VALIDATION
/*LPBufInternal lpBufOrig = LPBufIntFromLPBufExt(lpv);
if (IsBadWritePtr(lpBufOrig, sizeof(BufInternal))) { TellBadBlock(lpv, "fails address check"); return MAPI_E_INVALID_PARAMETER; } if (GetFlags(lpBufOrig->ulAllocFlags) != ALLOC_WITH_ALLOC) { TellBadBlock(lpv, "has invalid allocation flags"); return MAPI_E_INVALID_PARAMETER; } */ if (IsBadWritePtr(lppv, sizeof(LPVOID))) { DebugTraceArg(MAPIAllocateMore, TEXT("lppv fails address check")); return MAPI_E_INVALID_PARAMETER; } #endif /* PARAMETER_VALIDATION */
sc = MAPIAllocateMoreExt(heapidClient, ulSize, lpv, lppv);
DebugTraceSc(MAPIAllocateMore, sc); return sc; }
/*
* MAPIFreeBuffer * * Purpose: * Frees a memory block (or chain of blocks). * Frees any additional blocks linked with MAPIAllocateMore to * the buffer argument. Uses hHeap in the block header to * determine which heap to free into. * * Arguments: * lpv Pointer to a buffer allocated with MAPIAllocateBuffer. * lpv may be null, in which case we return immediately. * * Assumes: * This routine validates that lpv points to writable memory, * and was allocated with MAPIAllocateBuffer. * * Returns: * O if successful, lpv if unsuccessful. * If we are partially successful, i.e. the original block is * freed but the chain is corrupt further on, returns 0. * */ #ifndef WIN16
STDAPI_(ULONG) MAPIFreeBuffer(LPVOID lpv) #else
ULONG FAR PASCAL MAPIFreeBuffer(LPVOID lpv) #endif
{ LPBufInternal lpBufInt; LPBufInternal lpT; HLH hlh; int heapid;
if (!lpv) return(0L); // for callers who don't check for NULL themselves.
if (lpfnFreeBufferExternal) { return(lpfnFreeBufferExternal(lpv)); } lpBufInt = LPBufIntFromLPBufExt(lpv);
#ifdef PARAMETER_VALIDATION
// NOTE: these validations should be exactly the same as those
// that cause FValidAllocChain to return FALSE.
if (IsBadWritePtr(lpBufInt, sizeof(BufInternal))) { TellBadBlock(lpv, TEXT("fails address check")); return E_FAIL; } if (GetFlags(lpBufInt->ulAllocFlags) != ALLOC_WITH_ALLOC) { TellBadBlock(lpv, TEXT("has invalid allocation flags")); return E_FAIL; } #endif
// No CS used, as the internal heap is serialized.
// Only the AllocMore needs a CS, the Free does not; freeing
// a block whilst someone else is allocing more against it is
// asking for trouble!
// Note also that neither MAPIAllocateBuffer nor MAPIAllocateMore
// allow callers to use them when pinst->cRef == 0. MAPIFreeBuffer
// allows itself to be called in that case because simple MAPI
// needs to be able to free memory up until the DLL is unloaded.
#ifdef DEBUG
// This call checks flags and addresses for the whole chain.
// This means that, in DEBUG, we'll leak all of a chain that's
// corrupted after the first block. In SHIP, on the other hand,
// we'll free everything up until the broken link.
// But we do not return an error, for consistency.
if (!FValidAllocChain(lpBufInt)) goto ret; #endif
// Free the first block, using its allocator
lpT = lpBufInt->pLink;
heapid = GetHeapid(lpBufInt->ulAllocFlags); if (ScGetHlh(heapid, &hlh)) { DebugTrace( TEXT("MAPIFreeBuffer: playing in a heap that's gone\n")); return E_FAIL; } Assert(hlh == lpBufInt->hHeap); LH_Free(hlh, lpBufInt);
lpBufInt = lpT;
while (lpBufInt) { // NOTE: these validations should be exactly the same as those
// that cause FValidAllocChain to return FALSE.
if (IsBadWritePtr(lpBufInt, sizeof(BufInternal)) || GetFlags(lpBufInt->ulAllocFlags) != ALLOC_WITH_ALLOC_MORE) goto ret;
lpT = lpBufInt->pLink;
// Usually, chained buffers live in the same heap. We can do
// less work in this common case.
if ((int) GetHeapid(lpBufInt->ulAllocFlags) == heapid) LH_Free(hlh, lpBufInt); else { HLH hlhMore;
if (!ScGetHlh(GetHeapid(lpBufInt->ulAllocFlags), &hlhMore)) LH_Free(hlhMore, lpBufInt); else { DebugTrace(TEXT("MAPIFreeBuffer: playing in a chained heap that's gone\n")); }
} lpBufInt = lpT; }
ret: return 0; }
#ifdef OLD_STUFF
/*----------------------------------------------*/ /* Beginning of Provider Allocators */ /*----------------------------------------------*/
/*
* MAPIAllocateBufferProv * * Purpose: * Same as MAPIAllocateBuffer except uses the Service * Providers heap - pinst->hlhProvider. */
STDMETHODIMP_(SCODE) MAPIAllocateBufferProv(ULONG ulSize, LPVOID * lppv) { SCODE sc = S_OK;
#ifdef DEBUG
// Initialize flag that controls how noisy we are about invalid
// blocks passed to us.
if (fAssertBadBlocks == -1) { fAssertBadBlocks = GetPrivateProfileInt("General", "AssertBadBlocks", 1, "WABDBG.INI"); } #endif
#ifdef PARAMETER_VALIDATION
if (IsBadWritePtr((LPVOID) lppv, sizeof (LPVOID))) { DebugTraceArg(MAPIAllocateBuffer, TEXT("lppv fails address check")); return MAPI_E_INVALID_PARAMETER; } #endif
sc = MAPIAllocateBufferExt(heapidProvider, ulSize, lppv);
DebugTraceSc(MAPIAllocateBufferProv, sc); return sc; }
/*
* MAPIAllocateMoreProv * * Purpose: * Same as MAPIAllocateMore except uses the Service * Providers heap - pinst->hlhProvider. */
STDMETHODIMP_(SCODE) MAPIAllocateMoreProv(ULONG ulSize, LPVOID lpv, LPVOID * lppv) { SCODE sc = S_OK;
#ifdef PARAMETER_VALIDATION
LPBufInternal lpBufOrig = LPBufIntFromLPBufExt(lpv);
if (IsBadWritePtr(lpBufOrig, sizeof(BufInternal))) { TellBadBlock(lpv, "fails address check"); return MAPI_E_INVALID_PARAMETER; } if (GetFlags(lpBufOrig->ulAllocFlags) != ALLOC_WITH_ALLOC) { TellBadBlock(lpv, "has invalid allocation flags"); return MAPI_E_INVALID_PARAMETER; } if (IsBadWritePtr(lppv, sizeof(LPVOID))) { DebugTraceArg(MAPIAllocateMore, TEXT("lppv fails address check")); return MAPI_E_INVALID_PARAMETER; } #endif /* PARAMETER_VALIDATION */
sc = MAPIAllocateMoreExt(heapidProvider, ulSize, lpv, lppv);
DebugTraceSc(MAPIAllocateMoreProv, sc); return sc; } #endif
/*----------------------------------------------*/ /* Beginning of Extended Allocators */ /*----------------------------------------------*/
/*
* MAPIAllocateBufferExt * * Purpose: * Allocates a memory buffer on the specified heap. Can be * freed with MAPIFreeBuffer(). * * Arguments: * heapid in identifies the heap we wish to allocate in * pinst in Pointer to our instance data * ulSize in Size, in bytes, of the buffer to be allocated. * lppv out Pointer to variable where the address of the * allocated memory will be returned. * * Returns: * sc Indicating error if any (see below) * * Side effects: * Increments allocation count in the INST. * * Errors: * MAPI_E_INSUFFICIENT_MEMORY Allocation failed. * MAPI_E_INVALID_PARAMETER Second argument is invalid. * MAPI_E_INVALID_PARAMETER ulSize is out of range (>= 65535 on Win16). */
STDMETHODIMP_(SCODE) MAPIAllocateBufferExt(int heapid, ULONG ulSize, LPVOID * lppv) { SCODE sc = S_OK; LPBufInternal lpBufInt; HLH hlh;
// Don't allow allocation to wrap across 32 bits, or to exceed 64K
// under win16.
if ( ulSize > INT_SIZE (ulSize) #ifdef WIN16
|| (INT_SIZE(ulSize) >= 0x10000) #endif
) { DebugTrace(TEXT("MAPIAllocateBuffer: ulSize %ld is way too big\n"), ulSize); sc = MAPI_E_NOT_ENOUGH_MEMORY; goto ret; }
if (sc = ScGetHlh(heapid, &hlh)) goto ret;
lpBufInt = (LPBufInternal)LH_Alloc(hlh, (UINT) INT_SIZE(ulSize));
if (lpBufInt) { #ifdef DEBUG
lpBufInt->hHeap = hlh; #endif
lpBufInt->pLink = NULL; lpBufInt->ulAllocFlags = ALLOC_WITH_ALLOC | heapid; *lppv = (LPVOID) LPBufExtFromLPBufInt(lpBufInt); } else { DebugTrace(TEXT("MAPIAllocateBuffer: not enough memory for %ld\n"), ulSize); sc = MAPI_E_NOT_ENOUGH_MEMORY; }
ret: return sc; }
/*
* MAPIAllocateMoreExt * * Purpose: * Allocates a linked memory buffer on the specified heap, in such * a way that it can be freed with one call to MAPIFreeBuffer * (passing the buffer the client originally allocated with * MAPIAllocateBuffer). * * Arguments: * heapid in Identifies the heap we wish to allocate in * ulSize in Size, in bytes, of the buffer to be allocated. * lpv in Pointer to a buffer allocated with MAPIAllocateBuffer. * lppv out Pointer to variable where the address of the * allocated memory will be returned. * * Assumes: * Validates that lpBufOrig and lppv point to writable memory. * Validate that ulSize is less than 64K (on Win16 only) and that * lpBufOrig was allocated with MAPIAllocateBuffer. * * Returns: * sc Indicating error if any (see below) * * Side effects: * None * * Errors: * MAPI_E_INSUFFICIENT_MEMORY Allocation failed. * MAPI_E_INVALID_PARAMETER Second or third argument is invalid. * MAPI_E_INVALID_PARAMETER ulSize is out of range (>= 65535). */
STDMETHODIMP_(SCODE) MAPIAllocateMoreExt(int heapid, ULONG ulSize, LPVOID lpv, LPVOID * lppv) { SCODE sc = S_OK; LPBufInternal lpBufInt; LPBufInternal lpBufOrig; HLH hlh;
lpBufOrig = LPBufIntFromLPBufExt(lpv);
// Don't allow allocation to wrap across 32 bits, or to be
// greater than 64K under win16.
if ( ulSize > INT_SIZE (ulSize) #ifdef WIN16
|| (INT_SIZE(ulSize) >= 0x10000) #endif
) { DebugTrace(TEXT("MAPIAllocateMore: ulSize %ld is way too big\n"), ulSize); sc = MAPI_E_NOT_ENOUGH_MEMORY; goto ret; }
#ifdef DEBUG
//$ BUG Difference in behavior between DEBUG and SHIP:
// this validation will cause the call to fail in DEBUG if the
// tail of a chain is corrupted, while the SHIP version will
// add the new block at the (valid) head without checking.
if (!FValidAllocChain(lpBufOrig)) { sc = MAPI_E_INVALID_PARAMETER; goto ret; } #endif
if (sc = ScGetHlh(heapid, &hlh)) goto ret;
// Allocate the chained block and hook it to the head of the chain.
// In DEBUG, a separately wrapped allocator is used so that
// we report the number of chains leaked, not the number of blocks.
// In SHIP, they're the same allocator.
lpBufInt = (LPBufInternal)LH_Alloc(hlh, (UINT) INT_SIZE (ulSize));
if (lpBufInt) { #ifdef DEBUG
{ HLH hlhOrig; if (!ScGetHlh(GetHeapid(lpBufOrig->ulAllocFlags), &hlhOrig)) LH_SetName1(hlh, lpBufInt, TEXT("+ %s"), LH_GetName(hlhOrig, lpBufOrig)); } #endif
// Serialize the smallest possible code section
#ifdef DEBUG
lpBufInt->hHeap = hlh; #endif
lpBufInt->ulAllocFlags = ALLOC_WITH_ALLOC_MORE | heapid; EnterCriticalSection(&csHeap); lpBufInt->pLink = lpBufOrig->pLink; lpBufOrig->pLink = lpBufInt; LeaveCriticalSection(&csHeap); *lppv = (LPVOID) LPBufExtFromLPBufInt(lpBufInt); } else { DebugTrace(TEXT("MAPIAllocateMore: not enough memory for %ld\n"), ulSize); sc = MAPI_E_NOT_ENOUGH_MEMORY; }
ret: return sc; }
#ifdef OLD_STUFF
/*
* MAPIReallocateBuffer * * Purpose: * Allocates a memory buffer on the heap of the original allocation. * Can be freed with MAPIFreeBuffer(). * * Arguments: * lpv in original pointer * ulSize in new size, in bytes, of the buffer to be allocated. * lppv out pointer to variable where the address of the * allocated memory will be returned. * * Returns: * sc Indicating error if any (see below) * * Errors: * MAPI_E_NOT_ENOUGH_MEMORY Allocation failed. */
STDMETHODIMP_(SCODE) MAPIReallocateBuffer(LPVOID lpv, ULONG ulSize, LPVOID * lppv) { LPBufInternal lpBufInt; LPBufInternal lpBufIntNew; HLH hlh; // Do a real allocation if NULL is passed in as the base
//
if (!lpv) return MAPIAllocateBuffer (ulSize, lppv);
// Don't allow allocation to wrap across 32 bits, or to exceed 64K
// under win16.
//
if (ulSize > INT_SIZE (ulSize) #ifdef WIN16
|| (INT_SIZE(ulSize) >= 0x10000) #endif
) { DebugTrace(TEXT("MAPIReallocateBuffer: ulSize %ld is way too big\n"), ulSize); return MAPI_E_NOT_ENOUGH_MEMORY; }
lpBufInt = LPBufIntFromLPBufExt (lpv); if (ScGetHlh(GetHeapid(lpBufInt->ulAllocFlags), &hlh)) { DebugTrace(TEXT("MAPIReallocateBuffer: playing in a heap that's gone\n")); return MAPI_E_NOT_INITIALIZED; } Assert(hlh == lpBufInt->hHeap); if ((lpBufInt->ulAllocFlags & ALLOC_WITH_ALLOC) != ALLOC_WITH_ALLOC) return MAPI_E_INVALID_PARAMETER;
lpBufIntNew = (LPBufInternal)LH_Realloc (hlh, lpBufInt, (UINT) INT_SIZE(ulSize)); if (lpBufIntNew) { Assert (lpBufIntNew->hHeap == hlh); *lppv = (LPVOID) LPBufExtFromLPBufInt (lpBufIntNew); } else { DebugTrace ( TEXT("MAPIReallocateBuffer: not enough memory for %ld\n"), ulSize); return MAPI_E_NOT_ENOUGH_MEMORY; } return S_OK; } #endif // OLD_STUFF
#ifdef _WIN64
void WabValidateClientheap() { LPINSTUTIL pinstUtil; pinstUtil = (LPINSTUTIL) PvGetInstanceGlobalsEx(lpInstUtil); Assert(pinstUtil); Assert(HeapValidate(pinstUtil->hlhClient->_hlhBlks, 0, NULL)); Assert(HeapValidate(pinstUtil->hlhClient->_hlhData, 0, NULL)); }
#endif
/*
- ScGetHlh - * Purpose: * Finds the heap handle for a given heap ID. * * Arguments: * heapid in identifies the heap * Currently supports two: heapidClient and * heapidProvider. * hlh out the desired handle * * Returns: * SCODE * * Errors: * MAPI_E_NOT_INITIALIZED if the instance data that's supposed to * know about the heap is unavailable. */ SCODE ScGetHlh(int heapid, HLH FAR *phlh) { LPINSTUTIL pinstUtil; LPINST pinst;
switch (heapid) { case heapidClient: pinstUtil = (LPINSTUTIL) PvGetInstanceGlobalsEx(lpInstUtil); if (pinstUtil) { Assert(pinstUtil->hlhClient); #ifdef _WIN64 // additional check for Win64 (YST)
Assert(HeapValidate(pinstUtil->hlhClient->_hlhBlks, 0, NULL)); Assert(HeapValidate(pinstUtil->hlhClient->_hlhData, 0, NULL)); #endif
*phlh = pinstUtil->hlhClient; return S_OK; } else { DebugTrace(TEXT("ScGetHlh: INSTUTIL not available\n")); return MAPI_E_NOT_INITIALIZED; } break;
case heapidProvider: // Note: do not acquire the INST critical section.
// That frequently leads to deadlocks. We use our own
// critical section specifically to protect the heaps.
pinst = (LPINST) PvGetInstanceGlobals(); if (pinst && pinst->cRef) { Assert(pinst->hlhProvider); #ifdef _WIN64 // additional check for Win64 (YST)
Assert(HeapValidate(pinst->hlhProvider->_hlhBlks, 0, NULL)); #endif
*phlh = pinst->hlhProvider; return S_OK; } else { DebugTrace(TEXT("ScGetHlh: INST not available\n")); return MAPI_E_NOT_INITIALIZED; } break; }
TrapSz1( TEXT("HlhOfHeapid: unknown heap ID %d"), heapid); return MAPI_E_CALL_FAILED; }
#ifdef DEBUG
/*
* This function validates a block of memory, and any blocks * linked to it. * * NOTE: This is DEBUG-only code. To prevent differences in behavior * between debug and retail builds, any conditions that are not * checked in the retail code should only be asserted here -- they * should not cause a FALSE return. Currently the retail code does * not validate with DidAlloc(); it simply checks for accessibility * of the memory and the correct flag values. * * Whether this function generates asserts or debug trace output * is governed by a flag read from WABDBG.INI. */
BOOL FValidAllocChain(LPBufInternal lpBuf) { LPBufInternal lpBufTemp;
if (IsBadWritePtr(lpBuf, sizeof(BufInternal))) { TellBadBlockInt(lpBuf, TEXT("fails address check")); return FALSE; } if (GetFlags(lpBuf->ulAllocFlags) != ALLOC_WITH_ALLOC) { TellBadBlockInt(lpBuf, TEXT("has invalid flags")); return FALSE; }
for (lpBufTemp = lpBuf->pLink; lpBufTemp; lpBufTemp = lpBufTemp->pLink) { if (IsBadWritePtr(lpBufTemp, sizeof(BufInternal))) { TellBadBlockInt(lpBufTemp, TEXT("(linked block) fails address check")); return FALSE; } if (GetFlags(lpBufTemp->ulAllocFlags) != ALLOC_WITH_ALLOC_MORE) { TellBadBlockInt(lpBufTemp, TEXT("(linked block) has invalid flags")); return FALSE; } }
return TRUE; }
#endif // DEBUG
|