⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 heap.c

📁 不错的东西 请查看 WINCE OS
💻 C
📖 第 1 页 / 共 5 页
字号:
                }

                // release CS
                LeaveCriticalSection(&php->cs);

                // zero memory if requested
                if (pRet && (dwFlags & HEAP_ZERO_MEMORY)) {
#if HEAP_SENTINELS
                    memset ((char*)pRet + cbOrigSize, 0, dwBytes - cbOrigSize);
#else
                    memset ((char*)pit + cbOrigSize, 0, cbSeek - cbOrigSize);
#endif
                }
            }

        } else {

            if (cbItem > (int) (cbSeek + sizeof(item) + HEAP_SENTINELS)) {
                pitem pitNew = (pitem)((char*)pit + cbSeek);
                cbItem -= cbSeek;
                pitNew->size = -cbItem;
                pitNew->prgn = prgn;
                DEBUGMSG(DBGFIXHP, (L"   11:HeapReAlloc pitNew = %8.8lx (%8.8lx)\n", pitNew, pitNew->size));

                EnterCriticalSection (&php->cs);
                pit->size = cbSeek;     // Shrink the orginal block

                // we seems to do better without merging it here
                //MergeFreeItems (prgn, pitNew);

                if (prgn->cbMaxFree < cbItem) {
                    // the state of estimate does not change because of this
                    prgn->cbMaxFree = cbItem | (prgn->cbMaxFree & REGION_MAX_IS_ESTIMATE);
                }

#if HEAP_SENTINELS
                SetFreeSentinels (pitNew);
                SetSentinels(pit, dwBytes);
#endif
                LeaveCriticalSection (&php->cs);
                DEBUGMSG(DBGFIXHP, (L"   12:HeapReAlloc pit = %8.8lx (%8.8lx)\n", pit, pit->size));
            }
#if HEAP_SENTINELS
            else {
                // If the size is changing, we must update the sentinels and
                // possibly zero out a few bytes.
                if ((dwSize = pit->cbTrueSize) != dwBytes) {
                    SetSentinels(pit, dwBytes);
                    if (dwSize < dwBytes && (dwFlags & HEAP_ZERO_MEMORY))
                        memset((char*)(pit+1)+dwSize, 0, dwBytes-dwSize);
                }
            }
#endif
            pRet = pit+1;

        }
    }

    if (pit && !pRet && !(dwFlags & HEAP_REALLOC_IN_PLACE_ONLY)) {
        if ((pRet = Int_HeapAlloc(hHeap, dwFlags & HEAP_GENERATE_EXCEPTIONS, dwBytes)) != 0) {
#if HEAP_SENTINELS
            cbItem = pit->cbTrueSize;
            memcpy(pRet, pit+1, cbItem);
            if (dwFlags & HEAP_ZERO_MEMORY)
                memset((char*)pRet+cbItem, 0, dwBytes - cbItem);
#else
            cbItem = (pit->size & ~1) - sizeof(item);
            memcpy(pRet, pit+1, cbItem);
            if (dwFlags & HEAP_ZERO_MEMORY) {
                // Zero out tail of data that wasn't copied.
                int cbNew = (((pitem)pRet)[-1].size & ~1) - sizeof(item);
                if (cbNew > cbItem)
                    memset((char*)pRet+cbItem, 0, cbNew - cbItem);
            }
#endif
            // The new block has been allocated and the contents of the old block have been
            // copied to it.  Now free the old block.
            Int_HeapFree(hHeap, dwFlags & HEAP_GENERATE_EXCEPTIONS, lpMem);
        }
    } else if (!pRet)
        SetLastError(ERROR_NOT_ENOUGH_MEMORY);

    DEBUGMSG(DBGFIXHP, (L"   9:HeapReAlloc %8.8lx %8.8lx %8.8lx %8.8lx ==> %8.8lx\r\n", hHeap,dwFlags,lpMem,dwBytes,pRet));
    DEBUGCHK(!pRet || ((Int_HeapSize(hHeap,0,pRet) >= dwBytes) && (Int_HeapSize(hHeap,0,pRet) != (DWORD)-1)));
    if (IsCeLogStatus(CELOGSTATUS_ENABLED_GENERAL)) {
        CELOG_HeapRealloc(hHeap, dwFlags, dwBytes, (DWORD)lpMem, (DWORD)pRet);
    }
    return bZeroPtr ? (LPVOID)ZeroPtr(pRet) : pRet;
}

/*
    @doc BOTH EXTERNAL

    @func LPVOID | HeapAlloc | Allocates a block of memory from specified heap
    @parm HANDLE | hHeap     | Handle returned from CreateHeap()
    @parm DWORD  | dwFlags   | HEAP_NO_SERIALIZE and HEAP_ZERO_MEM supported
    @parm DWORD  | dwBytes   | Desired size of block
*/
LPVOID WINAPI HeapAlloc(HANDLE hHeap, DWORD dwFlags, DWORD dwBytes)
{
    return ptrHeapAlloc(hHeap, dwFlags, dwBytes);
}
LPVOID WINAPI HeapAllocTrace(HANDLE hHeap, DWORD dwFlags, DWORD dwBytes, DWORD dwLineNum, PCHAR szFilename)
{
    // If it's redirected then call it, otherwise ignore the trace params and call HeapAlloc
    if (ptrHeapAllocTrace) {
        return ptrHeapAllocTrace(hHeap, dwFlags, dwBytes, dwLineNum, szFilename);
    } else {
        return ptrHeapAlloc(hHeap, dwFlags, dwBytes);
    }
}
LPVOID WINAPI Int_HeapAlloc(HANDLE hHeap, DWORD dwFlags, DWORD dwBytes)
{
    pheap   php = (pheap) hHeap;
    pregion prgn;
    LPVOID  lpSlot;
    pitem   pitRet;

    //
    // check parameters
    //

    lpSlot = (char*)php - (DWORD)ZeroPtr(php);
    if ((dwFlags & ~(HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY)) || !hHeap || php->dwSig != HEAPSIG) {
        DEBUGMSG(DBGFIXHP, (L"   HeapAlloc %8.8lx %8.8lx %8.8lx ==> %8.8lx (invalid parameter)\r\n", hHeap,dwFlags,dwBytes,0));
        SetLastError(ERROR_INVALID_PARAMETER);
        return NULL;
    }
    if (dwBytes > HEAP_MAX_ALLOC) {
        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
        return NULL;
    }



    if (!php->cbMaximum && (dwBytes+sizeof(vaitem) >= CE_VALLOC_MINSIZE)) {
        // size requested is greated that VA threshold, use VirtualAlloc
        pitRet = DoLargeHeapAlloc (lpSlot, php, dwBytes);
#ifdef HEAP_STATISTICS
        InterlockedIncrement (&lNumAllocs[BUCKET_VIRTUAL]);
#endif
    } else {
        // ordinary HeapAlloc
        int cbSeek = ALIGNSIZE(dwBytes + sizeof(item) + HEAP_SENTINELS);
#ifdef HEAP_STATISTICS
        int idx = (cbSeek >> 4) - 1;   // slot number

        if (idx > BUCKET_LARGE)      // idx BUCKET_LARGE is for items >= 1K in size
            idx = BUCKET_LARGE;

        InterlockedIncrement (&lNumAllocs[idx]);
#endif

        // grab CS if serialized.
        EnterCriticalSection (&php->cs);

        // try allocating in existing regions
        if (!(pitRet = FindFreeItem (lpSlot, php, cbSeek, &prgn))   // try existing region first
            && !php->cbMaximum                                      // can we grow?
            && (prgn = CreateNewRegion (lpSlot, php, cbSeek))) {    // enough memory to create a new region?
            // if we can't find it in existing regions, try to create new regions
            pitRet = FIRSTITEM (prgn);
        }

        if (pitRet) {
            // carve the size requested from the free item found
            pitRet = CarveItem (prgn, pitRet, cbSeek, dwBytes, NULL);

#ifdef MEMTRACKING
            AddTrackedItem(php->wMemType, pitRet+1, TCB, GetCurrentProcessId(), pitRet->size, 0, 0);
#endif

        }
        LeaveCriticalSection (&php->cs);

        // Zero the memory block if requested.
        if ((dwFlags & HEAP_ZERO_MEMORY) && pitRet) {
#if HEAP_SENTINELS
            memset(pitRet+1, 0, pitRet->cbTrueSize);
#else
            memset(pitRet+1, 0, pitRet->size - sizeof(item));
#endif
        }
    }

    if (pitRet)
        ++pitRet;   // return the pointer AFTER the item header.

    if (IsCeLogStatus(CELOGSTATUS_ENABLED_GENERAL)) {
        CELOG_HeapAlloc(hHeap, dwFlags, dwBytes, (DWORD)pitRet);
    }
    DEBUGMSG(DBGFIXHP, (L"   HeapAlloc %8.8lx %8.8lx %8.8lx ==> %8.8lx\r\n", hHeap, dwFlags, dwBytes, pitRet));

    return lpSlot!=PSlot ? pitRet : (pitem)ZeroPtr(pitRet);

}


/*
    @doc BOTH EXTERNAL

    @func BOOL   | HeapFree | Frees a HeapAlloc'ed block of memory
    @parm HANDLE | hHeap    | Handle returned from CreateHeap()
    @parm DWORD  | dwFlags  | HEAP_NO_SERIALIZE only
    @parm LPVOID | lpMem    | Pointer to memory block
*/
BOOL WINAPI HeapFree(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem)
{
    return ptrHeapFree(hHeap, dwFlags, lpMem);
}
BOOL WINAPI Int_HeapFree(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem)
{
    pheap php;
    pitem pit;
    pregion prgn;
    int size;
    BOOL bRet = FALSE;

    php = (pheap)hHeap;
    if ((dwFlags & ~HEAP_NO_SERIALIZE) || !hHeap || php->dwSig != HEAPSIG || (DWORD)lpMem < 0x10000) {
        DEBUGMSG(DBGFIXHP, (L"   HeapFree %8.8lx %8.8lx %8.8lx ==> %8.8lx (invalid parameter)\r\n", hHeap,dwFlags,lpMem,0));
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }
    if (IsCeLogStatus(CELOGSTATUS_ENABLED_GENERAL)) {
        CELOG_HeapFree(hHeap, dwFlags, (DWORD)lpMem);
    }
    pit = (pitem)((char*)lpMem - sizeof(item));
    if (!((DWORD) pit >> VA_SECTION)) {
        // pit belongs to this heap, make sure it's slotized
        pit = (pitem) ((char *) pit + (DWORD)php - (DWORD)ZeroPtr(php));
    }

    size = pit->size;
    if (size > 0) {
#if HEAP_SENTINELS
        CheckSentinels(pit, TRUE);
#endif
        if (size & 1) {
            if (php == pit->php) {
                // VirtualAlloc'ed item.  Locate the vaitem structure for the block.
                // Remove the item from the heap's list, release the critical section (if serialized)
                // and then free the vitual memory block.
                pvaitem pva = (pvaitem)((char*)lpMem - sizeof(vaitem));
                DWORD   dwData = pva->dwData;

                EnterCriticalSection(&php->cs);
                if (pva->pvaBak == NULL) {
                    // This item is the head of the list.
                    DEBUGCHK(php->pvaList == pva || (pvaitem)ZeroPtr(php->pvaList) == pva);
                    if ((php->pvaList = pva->pvaFwd) != NULL)
                        php->pvaList->pvaBak = NULL;
                } else {
                    // Item in the middle or end of the list.
                    DEBUGCHK(php->pvaList != pva);
                    if ((pva->pvaBak->pvaFwd = pva->pvaFwd) != NULL)
                        pva->pvaFwd->pvaBak = pva->pvaBak;
                }
                LeaveCriticalSection(&php->cs);
                lpMem = (LPVOID)((DWORD)lpMem & -PAGE_SIZE);

                php->pfnFree (lpMem, size, MEM_DECOMMIT, dwData);
                php->pfnFree (lpMem, 0, MEM_RELEASE, dwData);
                bRet = TRUE;
            }

        } else if ((prgn = pit->prgn)->phpOwner == php) {

            EnterCriticalSection (&php->cs);

            pit->size = -size;
#if HEAP_SENTINELS
            // fill the item with 0xcc
            memset (pit+1, 0xcc, size - sizeof(item));
#endif

            MergeFreeItems (prgn, pit);

            if (prgn->cbMaxFree < -pit->size)
                prgn->cbMaxFree = -pit->size;

            prgn->cbMaxFree |= REGION_MAX_IS_ESTIMATE;

            LeaveCriticalSection (&php->cs);
            bRet = TRUE;
        }
    }

#ifdef MEMTRACKING
    if (bRet)
        DeleteTrackedItem(((pheap)hHeap)->dwMemType, lpMem);
#endif
    DEBUGMSG(DBGFIXHP, (L"   HeapFree %8.8lx %8.8lx %8.8lx ==> %8.8lx\r\n",hHeap,dwFlags,lpMem,bRet));
    return bRet;
}

/*
    @doc BOTH EXTERNAL

    @func DWORD | HeapSize | Returns the size of a HeapAlloc'ed block of memory
    @parm HANDLE | hHeap | Heap from which memory was alloc'ed
    @parm DWORD | dwFlags | can be HEAP_NO_SERIALIZE
    @parm LPVOID | lpMem | handle of local memory object to get size of

    @comm Follows the Win32 reference description without restrictions
    or modifications.
*/

DWORD WINAPI HeapSize(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem)
{
    return ptrHeapSize(hHeap, dwFlags, lpMem);
}
DWORD WINAPI Int_HeapSize(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem)
{
    UINT cbRet;
    pitem pit;
    pheap php;

    if ((dwFlags & ~HEAP_NO_SERIALIZE) || !hHeap || ((pheap)hHeap)->dwSig != HEAPSIG || (DWORD)lpMem < 0x10000) {
        DEBUGMSG(DBGFIXHP, (L"   HeapSize %8.8lx: Invalid parameter\r\n"));
        SetLastError(ERROR_INVALID_PARAMETER);
        return (DWORD)-1;
    }

    pit = (pitem)((char*)lpMem - sizeof(item));
    php = (pit->size&1) ? pit->php : pit->prgn->phpOwner;
    if (php == (pheap)hHeap && pit->size > 0) {
#if HEAP_SENTINELS
        CheckSentinels(pit, TRUE);
        cbRet = pit->cbTrueSize;
#else
        cbRet = (pit->size & -2) - sizeof(item);
#endif
    } else
        cbRet = (DWORD)-1;

    DEBUGMSG(DBGFIXHP, (L"   HeapSize %8.8lx ==> %8.8lx\r\n", lpMem, cbRet));
    return cbRet;
}

/*
    @doc BOTH EXTERNAL

    @func BOOL   | HeapDestroy | Destroys a heap and releases its memory
    @parm HANDLE | hHeap       | Handle returned from CreateHeap()
*/
BOOL WINAPI HeapDestroy(HANDLE hHeap)
{
    return ptrHeapDestroy(hHeap);
}
BOOL WINAPI Int_HeapDestroy(HANDLE hHeap)
{
    pheap php = (pheap)hHeap;
    pheap *pphp;
    pregion prgn;
    pvaitem pva;
    PFN_FreeHeapMem pfnFree;
    DWORD  dwRgnData;

    if (!hHeap || php->dwSig != HEAPSIG || (php->flOptions & HEAP_IS_PROC_HEAP)) {
        SetLastError(ERROR_INVALID_PARAMETER);
        DEBUGMSG(DBGFIXHP, (L"   HeapDestroy %8.8lx ==> %8.8lx (invalid parameter)\r\n", hHeap, 0));
        return FALSE;
    }
    if (IsCeLogStatus(CELOGSTATUS_ENABLED_GENERAL)) {
        CELOG_HeapDestroy(hHeap);
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -