mirror of
https://github.com/microsoft/Microsoft-3D-Movie-Maker.git
synced 2024-11-22 10:22:40 +01:00
238 lines
5.8 KiB
C++
238 lines
5.8 KiB
C++
|
/* Copyright (c) Microsoft Corporation.
|
||
|
Licensed under the MIT License. */
|
||
|
|
||
|
/***************************************************************************
|
||
|
Author: ShonK
|
||
|
Project: Kauai
|
||
|
Reviewed:
|
||
|
Copyright (c) Microsoft Corporation
|
||
|
|
||
|
Windows memory management.
|
||
|
|
||
|
***************************************************************************/
|
||
|
#include "util.h"
|
||
|
ASSERTNAME
|
||
|
|
||
|
|
||
|
struct HQH
|
||
|
{
|
||
|
long cb; // size of client area
|
||
|
long cactLock; // lock count
|
||
|
#ifdef DEBUG
|
||
|
long lwMagic; // for detecting memory trashing
|
||
|
#endif //DEBUG
|
||
|
};
|
||
|
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
long vcactSuspendCheckPointers = 0;
|
||
|
#endif //DEBUG
|
||
|
|
||
|
|
||
|
/***************************************************************************
|
||
|
Allocates a new moveable block.
|
||
|
***************************************************************************/
|
||
|
#ifdef DEBUG
|
||
|
bool FAllocHqDebug(HQ *phq, long cb, ulong grfmem, long mpr,
|
||
|
PSZS pszsFile, long lwLine)
|
||
|
#else //!DEBUG
|
||
|
bool FAllocHq(HQ *phq, long cb, ulong grfmem, long mpr)
|
||
|
#endif //!DEBUG
|
||
|
{
|
||
|
AssertVarMem(phq);
|
||
|
AssertIn(cb, 0, kcbMax);
|
||
|
HQH *phqh;
|
||
|
|
||
|
if (!FAllocPvDebug((void **)&phqh, cb + size(HQH), grfmem, mpr,
|
||
|
pszsFile, lwLine, &vdmglob.dmaglHq))
|
||
|
{
|
||
|
PushErc(ercOomHq);
|
||
|
*phq = hqNil;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
phqh->cb = cb;
|
||
|
phqh->cactLock = 0;
|
||
|
Debug( phqh->lwMagic = klwMagicMem; )
|
||
|
*phq = (HQ)(phqh + 1);
|
||
|
AssertHq(*phq);
|
||
|
}
|
||
|
|
||
|
return pvNil != *phq;
|
||
|
}
|
||
|
|
||
|
|
||
|
/***************************************************************************
|
||
|
Resizes the given hq. *phq may change. If fmemClear, clears any
|
||
|
newly added space.
|
||
|
***************************************************************************/
|
||
|
bool FResizePhq(HQ *phq, long cb, ulong grfmem, long mpr)
|
||
|
{
|
||
|
AssertVarMem(phq);
|
||
|
AssertHq(*phq);
|
||
|
AssertIn(cb, 0, kcbMax);
|
||
|
bool fRet = fFalse;
|
||
|
HQH *phqh = (HQH *)PvSubBv(*phq, size(HQH));
|
||
|
|
||
|
if (phqh->cactLock > 0)
|
||
|
{
|
||
|
Bug("Resizing locked HQ");
|
||
|
PushErc(ercOomHq);
|
||
|
}
|
||
|
else if (!_FResizePpvDebug((void **)&phqh, cb + size(HQH),
|
||
|
phqh->cb + size(HQH), grfmem, mpr, &vdmglob.dmaglHq))
|
||
|
{
|
||
|
PushErc(ercOomHq);
|
||
|
AssertHq(*phq);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
phqh->cb = cb;
|
||
|
*phq = (HQ)(phqh + 1);
|
||
|
AssertHq(*phq);
|
||
|
fRet = fTrue;
|
||
|
}
|
||
|
|
||
|
return fRet;
|
||
|
}
|
||
|
|
||
|
|
||
|
/***************************************************************************
|
||
|
If hq is not nil, frees it.
|
||
|
***************************************************************************/
|
||
|
void FreePhq(HQ *phq)
|
||
|
{
|
||
|
AssertVarMem(phq);
|
||
|
|
||
|
if (*phq == hqNil)
|
||
|
return;
|
||
|
|
||
|
AssertHq(*phq);
|
||
|
HQH *phqh = (HQH *)PvSubBv(*phq, size(HQH));
|
||
|
*phq = hqNil;
|
||
|
Assert(phqh->cactLock == 0, "Freeing locked HQ");
|
||
|
|
||
|
FreePpvDebug((void **)&phqh, &vdmglob.dmaglHq);
|
||
|
}
|
||
|
|
||
|
|
||
|
/***************************************************************************
|
||
|
Create a new HQ the same size as hqSrc and copy hqSrc into it.
|
||
|
***************************************************************************/
|
||
|
bool FCopyHq(HQ hqSrc, HQ *phqDst, long mpr)
|
||
|
{
|
||
|
AssertHq(hqSrc);
|
||
|
AssertVarMem(phqDst);
|
||
|
long cb;
|
||
|
|
||
|
if (!FAllocHq(phqDst, cb = CbOfHq(hqSrc), fmemNil, mpr))
|
||
|
return fFalse;
|
||
|
CopyPb(QvFromHq(hqSrc), QvFromHq(*phqDst), cb);
|
||
|
return fTrue;
|
||
|
}
|
||
|
|
||
|
|
||
|
/***************************************************************************
|
||
|
Return the size of the hq (the client area of the block).
|
||
|
***************************************************************************/
|
||
|
long CbOfHq(HQ hq)
|
||
|
{
|
||
|
AssertHq(hq);
|
||
|
HQH *phqh = (HQH *)PvSubBv(hq, size(HQH));
|
||
|
return phqh->cb;
|
||
|
}
|
||
|
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
/***************************************************************************
|
||
|
Returns a volatile pointer from an hq.
|
||
|
***************************************************************************/
|
||
|
void *QvFromHq(HQ hq)
|
||
|
{
|
||
|
AssertHq(hq);
|
||
|
return (void *)hq;
|
||
|
}
|
||
|
#endif //DEBUG
|
||
|
|
||
|
|
||
|
/***************************************************************************
|
||
|
Lock the hq and return a pointer to the data.
|
||
|
***************************************************************************/
|
||
|
void *PvLockHq(HQ hq)
|
||
|
{
|
||
|
AssertHq(hq);
|
||
|
HQH *phqh = (HQH *)PvSubBv(hq, size(HQH));
|
||
|
phqh->cactLock++;
|
||
|
Assert(phqh->cactLock > 0, "overflow in cactLock");
|
||
|
return (void *)hq;
|
||
|
}
|
||
|
|
||
|
|
||
|
/***************************************************************************
|
||
|
Unlock the hq. Asserts and does nothing if the lock count is zero.
|
||
|
***************************************************************************/
|
||
|
void UnlockHq(HQ hq)
|
||
|
{
|
||
|
AssertHq(hq);
|
||
|
HQH *phqh = (HQH *)PvSubBv(hq, size(HQH));
|
||
|
Assert(phqh->cactLock > 0, "hq not locked");
|
||
|
if (phqh->cactLock > 0)
|
||
|
--phqh->cactLock;
|
||
|
}
|
||
|
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
/***************************************************************************
|
||
|
Assert that a given hq is valid.
|
||
|
***************************************************************************/
|
||
|
void AssertHq(HQ hq)
|
||
|
{
|
||
|
// make sure hq isn't nil
|
||
|
if (hq == hqNil)
|
||
|
{
|
||
|
Bug("hq is nil");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// verify the HQH
|
||
|
HQH *phqh = (HQH *)PvSubBv(hq, size(HQH));
|
||
|
if (phqh->lwMagic != klwMagicMem)
|
||
|
{
|
||
|
BugVar("beginning of hq block is trashed", phqh);
|
||
|
return;
|
||
|
}
|
||
|
AssertIn(phqh->cactLock, 0, kcbMax);
|
||
|
AssertPvAlloced(phqh, phqh->cb + size(HQH));
|
||
|
}
|
||
|
|
||
|
|
||
|
/***************************************************************************
|
||
|
Increment the ref count on an hq.
|
||
|
***************************************************************************/
|
||
|
void MarkHq(HQ hq)
|
||
|
{
|
||
|
if (hqNil != hq)
|
||
|
{
|
||
|
AssertHq(hq);
|
||
|
MarkPv(PvSubBv(hq, size(HQH)));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/***************************************************************************
|
||
|
Make sure we can access a pointer's memory. If cb is 0, pv can be
|
||
|
anything (including nil).
|
||
|
***************************************************************************/
|
||
|
void AssertPvCb(void *pv, long cb)
|
||
|
{
|
||
|
if (vcactSuspendCheckPointers == 0 && cb != 0)
|
||
|
{
|
||
|
AssertVar(!IsBadWritePtr(pv, cb), "no write access to ptr", &pv);
|
||
|
// I (ShonK) am assuming that write access implies read access for
|
||
|
// memory, so it would just be a waste of time to call this.
|
||
|
// AssertVar(!IsBadReadPtr(pv, cb), "no read access to ptr", &pv);
|
||
|
}
|
||
|
}
|
||
|
#endif //DEBUG
|
||
|
|