Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

534 lines
11 KiB

#include "ctlspriv.h"
#ifdef DEBUG
#if defined(WIN32) && !defined(WINNT)
#define DEBUG_BREAK _try { _asm { int 3 } } _except (EXCEPTION_EXECUTE_HANDLER) {;}
#else
#define DEBUG_BREAK DebugBreak();
#endif
//========== Debug output routines =========================================
#ifdef DEBUG
UINT wDebugMask = 0; // this gets initialized in commctrl.c, _ProcessAttach()
#endif
UINT WINAPI SetDebugMask(UINT mask)
{
#ifdef DEBUG
UINT wOld = wDebugMask;
wDebugMask = mask;
return wOld;
#else
return 0;
#endif
}
UINT WINAPI GetDebugMask()
{
#ifdef DEBUG
return wDebugMask;
#else
return 0;
#endif
}
void WINAPI AssertFailed(LPCTSTR pszFile, int line)
{
#ifdef DEBUG
LPCTSTR psz;
TCHAR ach[256];
static TCHAR szAssertFailed[] = TEXT("Assertion failed in %s on line %d\r\n");
// Strip off path info from filename string, if present.
//
if (wDebugMask & DM_ASSERT)
{
for (psz = pszFile + lstrlen(pszFile); psz != pszFile; psz=AnsiPrev(pszFile, psz))
{
if ((AnsiPrev(pszFile, psz)!= (psz-2)) && *(psz - 1) == TEXT('\\'))
break;
}
wsprintf(ach, szAssertFailed, psz, line);
OutputDebugString(ach);
DEBUG_BREAK
}
#endif
}
void WINCAPI _AssertMsg(BOOL f, LPCTSTR pszMsg, ...)
{
#ifdef DEBUG
TCHAR ach[256];
va_list marker;
va_start( marker, pszMsg );
if (!f && (wDebugMask & DM_ASSERT))
{
wvsprintf(ach, pszMsg, marker);
OutputDebugString(ach);
OutputDebugString((LPCTSTR)TEXT("\r\n"));
DEBUG_BREAK
}
va_end(marker);
#endif
}
void WINCAPI _DebugMsg(UINT mask, LPCTSTR pszMsg, ...)
{
#ifdef DEBUG
#ifdef WIN32
TCHAR ach[2*MAX_PATH+40]; // Handles 2*largest path + slop for message
#else // WIN32
TCHAR ach[MAX_PATH+40]; // Handles largest path + slop for message
#endif // WIN32
va_list marker;
va_start( marker, pszMsg );
if (wDebugMask & mask)
{
wvsprintf(ach, pszMsg, marker);
OutputDebugString((LPCTSTR)TEXT("COMCTL32: "));
OutputDebugString(ach);
OutputDebugString((LPCTSTR)TEXT("\r\n"));
}
va_end(marker);
#endif
}
#endif //DEBUG
//========== Memory Management =============================================
#ifndef WIN32
#define MAX_WORD 0xffff
DECLARE_HANDLE(HHEAP);
typedef struct { // maps to the bottom of a 16bit DS
WORD reserved[8];
WORD cAlloc;
WORD cbAllocFailed;
HHEAP hhpFirst;
HHEAP hhpNext;
} HEAP;
#define PHEAP(hhp) ((HEAP FAR*)MAKELP(hhp, 0))
#define MAKEHP(sel, off) ((void _huge*)MAKELP((sel), (off)))
#define CBSUBALLOCMAX 0x0000f000L
HHEAP g_hhpFirst = NULL;
BOOL NEAR DestroyHeap(HHEAP hhp);
void Mem_Terminate()
{
while (g_hhpFirst)
DestroyHeap(g_hhpFirst);
}
BOOL NEAR CreateHeap(WORD cbInitial)
{
HHEAP hhp;
if (cbInitial < 1024)
cbInitial = 1024;
hhp = (HHEAP)GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT | GMEM_SHARE, cbInitial);
if (!hhp)
return FALSE;
if (!LocalInit((WORD)hhp, sizeof(HEAP), cbInitial - 1))
{
GlobalFree(hhp);
return FALSE;
}
PHEAP(hhp)->cAlloc = 0;
PHEAP(hhp)->cbAllocFailed = MAX_WORD;
PHEAP(hhp)->hhpNext = g_hhpFirst;
g_hhpFirst = hhp;
DebugMsg(DM_TRACE, TEXT("CreateHeap: added new local heap %x"), hhp);
return TRUE;
}
#pragma optimize("o", off) // linked list removals don't optimize correctly
BOOL NEAR DestroyHeap(HHEAP hhp)
{
Assert(hhp);
Assert(g_hhpFirst);
if (g_hhpFirst == hhp)
{
g_hhpFirst = PHEAP(hhp)->hhpNext;
}
else
{
HHEAP hhpT = g_hhpFirst;
while (PHEAP(hhpT)->hhpNext != hhp)
{
hhpT = PHEAP(hhpT)->hhpNext;
if (!hhpT)
return FALSE;
}
PHEAP(hhpT)->hhpNext = PHEAP(hhp)->hhpNext;
}
if (GlobalFree((HGLOBAL)hhp) != NULL)
return FALSE;
return TRUE;
}
#pragma optimize("", on) // back to default optimizations
#pragma optimize("lge", off) // Suppress warnings associated with use of _asm...
void NEAR* NEAR HeapAlloc(HHEAP hhp, WORD cb)
{
void NEAR* pb;
_asm {
push ds
mov ds,hhp
}
pb = (void NEAR*)LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, cb);
if (pb)
((HEAP NEAR*)0)->cAlloc++;
_asm {
pop ds
}
return pb;
}
#pragma optimize("o", off) // linked list removals don't optimize correctly
void _huge* WINAPI Alloc(long cb)
{
void NEAR* pb;
HHEAP hhp;
HHEAP hhpPrev;
// If this is a big allocation, just do a global alloc.
//
if (cb > CBSUBALLOCMAX)
{
void FAR* lpb = MAKEHP(GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT | GMEM_SHARE, cb), 0);
if (!lpb)
DebugMsg(DM_ERROR, TEXT("Alloc: out of memory"));
return lpb;
}
hhp = g_hhpFirst;
while (TRUE)
{
if (hhp == NULL)
{
if (!CreateHeap(0))
{
DebugMsg(DM_ERROR, TEXT("Alloc: out of memory"));
return NULL;
}
hhp = g_hhpFirst;
}
pb = HeapAlloc(hhp, (WORD)cb);
if (pb)
return MAKEHP(hhp, pb);
// Record the size of the allocation that failed.
// Later attempts to allocate more than this amount
// will not succeed. This gets reset anytime anything
// is freed in the heap.
//
PHEAP(hhp)->cbAllocFailed = (WORD)cb;
// First heap is full... see if there's room in any other heap...
//
for (hhpPrev = hhp; hhp = PHEAP(hhp)->hhpNext; hhpPrev = hhp)
{
// If the last allocation to fail in this heap
// is not larger than cb, don't even try an allocation.
//
if ((WORD)cb >= PHEAP(hhp)->cbAllocFailed)
continue;
pb = HeapAlloc(hhp, (WORD)cb);
if (pb)
{
// This heap had room: move it to the front...
//
PHEAP(hhpPrev)->hhpNext = PHEAP(hhp)->hhpNext;
PHEAP(hhp)->hhpNext = g_hhpFirst;
g_hhpFirst = hhp;
return MAKEHP(hhp, pb);
}
else
{
// The alloc failed. Set cbAllocFailed...
//
PHEAP(hhp)->cbAllocFailed = (WORD)cb;
}
}
}
}
#pragma optimize("", on) // back to default optimizations
#pragma optimize("lge", off) // Suppress warnings associated with use of _asm...
void _huge* WINAPI ReAlloc(void _huge* pb, long cb)
{
void NEAR* pbNew;
void _huge* lpbNew;
UINT cbOld;
// BUGBUG, does not work with cb > 64k
if (!pb)
return Alloc(cb);
if (OFFSETOF(pb) == 0)
return MAKEHP(GlobalReAlloc((HGLOBAL)SELECTOROF(pb), cb, GMEM_MOVEABLE | GMEM_ZEROINIT), 0);
_asm {
push ds
mov ds,word ptr [pb+2]
}
pbNew = (void NEAR*)LocalReAlloc((HLOCAL)OFFSETOF(pb), (int)cb, LMEM_MOVEABLE | LMEM_ZEROINIT);
if (!pbNew)
cbOld = LocalSize((HLOCAL)OFFSETOF(pb));
_asm {
pop ds
}
if (pbNew)
return MAKEHP(SELECTOROF(pb), pbNew);
lpbNew = Alloc(cb);
if (lpbNew)
{
hmemcpy((void FAR*)lpbNew, (void FAR*)pb, cbOld);
Free(pb);
}
else
{
DebugMsg(DM_ERROR, TEXT("ReAlloc: out of memory"));
}
return lpbNew;
}
BOOL WINAPI Free(void _huge* pb)
{
BOOL fSuccess;
UINT cAlloc;
if (OFFSETOF(pb) == 0)
return (GlobalFree((HGLOBAL)SELECTOROF(pb)) == NULL);
_asm {
push ds
mov ds,word ptr [pb+2]
}
fSuccess = (LocalFree((HLOCAL)OFFSETOF(pb)) ? FALSE : TRUE);
cAlloc = 1;
if (fSuccess)
{
cAlloc = --((HEAP NEAR*)0)->cAlloc;
((HEAP NEAR*)0)->cbAllocFailed = MAX_WORD;
}
_asm {
pop ds
}
if (cAlloc == 0)
DestroyHeap((HHEAP)SELECTOROF(pb));
return fSuccess;
}
DWORD WINAPI GetSize(void _huge* pb)
{
WORD wSize;
if (OFFSETOF(pb) == 0)
return GlobalSize((HGLOBAL)SELECTOROF(pb));
_asm {
push ds
mov ds,word ptr [pb+2]
}
wSize = LocalSize((HLOCAL)OFFSETOF(pb));
_asm {
pop ds
}
return (DWORD)wSize;
}
#pragma optimize("", on)
#else // WIN32
//----------------------------------------------------------------------------
// Define a Global Shared Heap that we use allocate memory out of that we
// Need to share between multiple instances.
HANDLE g_hSharedHeap = NULL;
#define GROWABLE 0
#define MAXHEAPSIZE GROWABLE //(2097152 * 2)
#define HEAP_SHARED 0x04000000 /* put heap in shared memory */
void Mem_Terminate()
{
// Assuming that everything else has exited
//
if (g_hSharedHeap != NULL)
HeapDestroy(g_hSharedHeap);
g_hSharedHeap = NULL;
}
void * WINAPI Alloc(long cb)
{
// I will assume that this is the only one that needs the checks to
// see if the heap has been previously created or not
if (g_hSharedHeap == NULL)
{
ENTERCRITICAL
if (g_hSharedHeap == NULL)
{
g_hSharedHeap = HeapCreate(HEAP_SHARED, 1, MAXHEAPSIZE);
}
LEAVECRITICAL
// If still NULL we have problems!
if (g_hSharedHeap == NULL)
return(NULL);
}
return HeapAlloc(g_hSharedHeap, HEAP_ZERO_MEMORY, cb);
}
void * WINAPI ReAlloc(void * pb, long cb)
{
if (pb == NULL)
return Alloc(cb);
return HeapReAlloc(g_hSharedHeap, HEAP_ZERO_MEMORY, pb, cb);
}
BOOL WINAPI Free(void * pb)
{
return HeapFree(g_hSharedHeap, 0, pb);
}
DWORD WINAPI GetSize(void * pb)
{
return HeapSize(g_hSharedHeap, 0, pb);
}
//----------------------------------------------------------------------------
// The following functions are for debug only and are used to try to
// calculate memory usage.
//
#ifdef DEBUG
typedef struct _HEAPTRACE
{
DWORD cAlloc;
DWORD cFailure;
DWORD cReAlloc;
DWORD cbMaxTotal;
DWORD cCurAlloc;
DWORD cbCurTotal;
} HEAPTRACE;
HEAPTRACE g_htShell = {0}; // Start of zero...
LPVOID WINAPI ControlAlloc(HANDLE hheap, DWORD cb)
{
LPVOID lp = HeapAlloc(hheap, HEAP_ZERO_MEMORY, cb);;
if (lp == NULL)
{
g_htShell.cFailure++;
return NULL;
}
// Update counts.
g_htShell.cAlloc++;
g_htShell.cCurAlloc++;
g_htShell.cbCurTotal += cb;
if (g_htShell.cbCurTotal > g_htShell.cbMaxTotal)
g_htShell.cbMaxTotal = g_htShell.cbCurTotal;
return lp;
}
LPVOID WINAPI ControlReAlloc(HANDLE hheap, LPVOID pb, DWORD cb)
{
LPVOID lp;
DWORD cbOld;
cbOld = HeapSize(hheap, 0, pb);
lp = HeapReAlloc(hheap, HEAP_ZERO_MEMORY, pb,cb);
if (lp == NULL)
{
g_htShell.cFailure++;
return NULL;
}
// Update counts.
g_htShell.cReAlloc++;
g_htShell.cbCurTotal += cb - cbOld;
if (g_htShell.cbCurTotal > g_htShell.cbMaxTotal)
g_htShell.cbMaxTotal = g_htShell.cbCurTotal;
return lp;
}
BOOL WINAPI ControlFree(HANDLE hheap, LPVOID pb)
{
DWORD cbOld = HeapSize(hheap, 0, pb);
BOOL fRet = HeapFree(hheap, 0, pb);
if (fRet)
{
// Update counts.
g_htShell.cCurAlloc--;
g_htShell.cbCurTotal -= cbOld;
}
return(fRet);
}
DWORD WINAPI ControlSize(HANDLE hheap, LPVOID pb)
{
return HeapSize(hheap, 0, pb);
}
#endif // DEBUG
#endif // WIN32
#if defined(FULL_DEBUG) && defined(WIN32)
#include "..\inc\deballoc.c"
#endif // defined(FULL_DEBUG) && defined(WIN32)