home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
xwphescr.zip
/
XWPH0208.ZIP
/
src
/
helpers
/
memdebug_win.c
< prev
next >
Wrap
C/C++ Source or Header
|
2002-06-02
|
31KB
|
847 lines
/*
*@@sourcefile memdebug_win.c:
* implementation of the PM heap debugging window,
* if the __XWPMEMDEBUG__ #define is set in setup.h.
*
* This has been extracted from memdebug.c to allow
* linking with non-PM programs.
*
*@@added V0.9.6 (2000-11-12) [umoeller]
*/
/*
* Copyright (C) 2000 Ulrich Möller.
* This program is part of the XWorkplace package.
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, in version 2 as it comes in the COPYING
* file of the XWorkplace main distribution.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#define OS2EMX_PLAIN_CHAR
// this is needed for "os2emx.h"; if this is defined,
// emx will define PSZ as _signed_ char, otherwise
// as unsigned char
#define INCL_DOSSEMAPHORES
#define INCL_DOSEXCEPTIONS
#define INCL_DOSPROCESS
#define INCL_DOSERRORS
#define INCL_WINWINDOWMGR
#define INCL_WINFRAMEMGR
#define INCL_WINCOUNTRY
#define INCL_WINSYS
#define INCL_WINMENUS
#define INCL_WINSTDCNR
#include <os2.h>
#include <stdio.h>
#include <string.h>
// #include <malloc.h>
#include <setjmp.h>
#include "helpers\tree.h"
#define DONT_REPLACE_MALLOC // never do debug memory for this
#define MEMDEBUG_PRIVATE
#include "setup.h"
#ifdef __XWPMEMDEBUG__
#include "helpers\cnrh.h"
#include "helpers\except.h"
// #include "helpers\memdebug.h" // included by setup.h already
#include "helpers\nls.h"
#include "helpers\stringh.h"
#include "helpers\winh.h"
/*
*@@category: Helpers\C helpers\Heap debugging
*/
/* ******************************************************************
*
* Global variables
*
********************************************************************/
PSZ G_pszMemCnrTitle = NULL;
HWND G_hwndMemDebugMenu = NULLHANDLE;
/* ******************************************************************
*
* Heap debugging window
*
********************************************************************/
/*
*@@ MEMRECORD:
*
*@@added V0.9.1 (99-12-04) [umoeller]
*/
typedef struct _MEMRECORD
{
RECORDCORE recc;
ULONG ulIndex;
CDATE cdateAllocated;
CTIME ctimeAllocated;
PSZ pszFreed;
ULONG ulTID;
PSZ pszFunction; // points to szFunction
CHAR szFunction[400];
PSZ pszSource; // points to szSource
CHAR szSource[CCHMAXPATH];
ULONG ulLine;
ULONG ulAddress; // has pAfterMagic, invisible, only
// for sorting V0.9.14 (2001-08-01) [umoeller]
PSZ pszAddress; // points to szAddress
CHAR szAddress[20];
ULONG ulSize;
} MEMRECORD, *PMEMRECORD;
/* ULONG ulHeapItemsCount1,
ulHeapItemsCount2;
ULONG ulTotalAllocated,
ulTotalFreed;
PMEMRECORD pMemRecordThis = NULL;
PSZ pszMemCnrTitle = NULL; */
#if 0
/*
*@@ fncbMemHeapWalkCount:
* callback func for _heap_walk function used for
* fnwpMemDebug.
*
*@@added V0.9.1 (99-12-04) [umoeller]
*/
int fncbMemHeapWalkCount(const void *pObject,
size_t Size,
int useflag,
int status,
const char *filename,
size_t line)
{
// skip all the items which seem to be
// internal to the runtime
if ((filename) || (useflag == _FREEENTRY))
{
ulHeapItemsCount1++;
if (useflag == _FREEENTRY)
ulTotalFreed += Size;
else
ulTotalAllocated += Size;
}
return (0);
}
/*
*@@ fncbMemHeapWalkFill:
* callback func for _heap_walk function used for
* fnwpMemDebug.
*
*@@added V0.9.1 (99-12-04) [umoeller]
*/
int fncbMemHeapWalkFill(const void *pObject,
size_t Size,
int useflag,
int status,
const char *filename,
size_t line)
{
// skip all the items which seem to be
// internal to the runtime
if ((filename) || (useflag == _FREEENTRY))
{
ulHeapItemsCount2++;
if ((pMemRecordThis) && (ulHeapItemsCount2 < ulHeapItemsCount1))
{
pMemRecordThis->ulIndex = ulHeapItemsCount2 - 1;
pMemRecordThis->pObject = pObject;
pMemRecordThis->useflag = useflag;
pMemRecordThis->status = status;
pMemRecordThis->filename = filename;
pMemRecordThis->pszAddress = pMemRecordThis->szAddress;
pMemRecordThis->ulSize = Size;
pMemRecordThis->pszSource = pMemRecordThis->szSource;
pMemRecordThis->ulLine = line;
pMemRecordThis = (PMEMRECORD)pMemRecordThis->recc.preccNextRecord;
}
else
return (1); // stop
}
return (0);
}
/*
*@@ CreateRecordsVAC:
*
*@@added V0.9.3 (2000-04-10) [umoeller]
*/
VOID CreateRecordsVAC(HWND hwndCnr)
{
// count heap items
ulHeapItemsCount1 = 0;
ulTotalFreed = 0;
ulTotalAllocated = 0;
_heap_walk(fncbMemHeapWalkCount);
pMemRecordFirst = (PMEMRECORD)cnrhAllocRecords(hwndCnr,
sizeof(MEMRECORD),
ulHeapItemsCount1);
if (pMemRecordFirst)
{
ulHeapItemsCount2 = 0;
pMemRecordThis = pMemRecordFirst;
_heap_walk(fncbMemHeapWalkFill);
// the following doesn't work while _heap_walk is running
pMemRecordThis = pMemRecordFirst;
while (pMemRecordThis)
{
switch (pMemRecordThis->useflag)
{
case _USEDENTRY: pMemRecordThis->pszUseFlag = "Used"; break;
case _FREEENTRY: pMemRecordThis->pszUseFlag = "Freed"; break;
}
switch (pMemRecordThis->status)
{
case _HEAPBADBEGIN: pMemRecordThis->pszStatus = "heap bad begin"; break;
case _HEAPBADNODE: pMemRecordThis->pszStatus = "heap bad node"; break;
case _HEAPEMPTY: pMemRecordThis->pszStatus = "heap empty"; break;
case _HEAPOK: pMemRecordThis->pszStatus = "OK"; break;
}
pMemRecordThis->ulAddress = (ULONG)pMemRecordThis->pObject;
sprintf(pMemRecordThis->szAddress,
"0x%lX",
pMemRecordThis->pObject);
strhcpy(pMemRecordThis->szSource,
(pMemRecordThis->filename)
? pMemRecordThis->filename
: "?");
pMemRecordThis = (PMEMRECORD)pMemRecordThis->recc.preccNextRecord;
}
cnrhInsertRecords(hwndCnr,
NULL, // parent
(PRECORDCORE)pMemRecordFirst,
TRUE,
NULL,
CRA_RECORDREADONLY,
ulHeapItemsCount2);
}
}
#endif
/*
*@@ CreateRecords:
*
*@@added V0.9.3 (2000-04-10) [umoeller]
*/
static VOID CreateRecords(HWND hwndCnr,
PULONG pulTotalItems,
PULONG pulAllocatedItems,
PULONG pulFreedItems,
PULONG pulTotalBytes,
PULONG pulAllocatedBytes,
PULONG pulFreedBytes)
{
// count heap items
// ULONG ulHeapItemsCount1 = 0;
PMEMRECORD pMemRecordFirst;
ULONG cHeapItems = 0;
BOOL fLocked = FALSE;
TRY_LOUD(excpt1)
{
if (fLocked = memdLock())
{
PHEAPITEM pHeapItem = (PHEAPITEM)treeFirst(G_pHeapItemsRoot);
*pulTotalItems = 0;
*pulAllocatedItems = 0;
*pulFreedItems = 0;
*pulTotalBytes = 0;
*pulAllocatedBytes = 0;
*pulFreedBytes = 0;
*pulTotalItems = G_cHeapItems;
if (pMemRecordFirst = (PMEMRECORD)cnrhAllocRecords(hwndCnr,
sizeof(MEMRECORD),
G_cHeapItems))
{
PMEMRECORD pMemRecordThis = pMemRecordFirst;
pHeapItem = (PHEAPITEM)treeFirst(G_pHeapItemsRoot);
while ((pMemRecordThis) && (pHeapItem))
{
if (pHeapItem->fFreed)
{
(*pulFreedItems)++;
(*pulFreedBytes) += pHeapItem->ulSize;
}
else
{
(*pulAllocatedItems)++;
(*pulAllocatedBytes) += pHeapItem->ulSize;
}
(*pulTotalBytes) += pHeapItem->ulSize;
pMemRecordThis->ulIndex = cHeapItems++;
cnrhDateTimeDos2Win(&pHeapItem->dtAllocated,
&pMemRecordThis->cdateAllocated,
&pMemRecordThis->ctimeAllocated);
if (pHeapItem->fFreed)
pMemRecordThis->pszFreed = "yes";
pMemRecordThis->ulTID = pHeapItem->ulTID;
strhcpy(pMemRecordThis->szSource, pHeapItem->pcszSourceFile);
pMemRecordThis->pszSource = pMemRecordThis->szSource;
pMemRecordThis->ulLine = pHeapItem->ulLine;
strhcpy(pMemRecordThis->szFunction, pHeapItem->pcszFunction);
pMemRecordThis->pszFunction = pMemRecordThis->szFunction;
pMemRecordThis->ulAddress = pHeapItem->Tree.ulKey;
sprintf(pMemRecordThis->szAddress,
"0x%lX",
pHeapItem->Tree.ulKey);
pMemRecordThis->pszAddress = pMemRecordThis->szAddress;
pMemRecordThis->ulSize = pHeapItem->ulSize;
/* switch (pMemRecordThis->useflag)
{
case _USEDENTRY: pMemRecordThis->pszUseFlag = "Used"; break;
case _FREEENTRY: pMemRecordThis->pszUseFlag = "Freed"; break;
}
switch (pMemRecordThis->status)
{
case _HEAPBADBEGIN: pMemRecordThis->pszStatus = "heap bad begin"; break;
case _HEAPBADNODE: pMemRecordThis->pszStatus = "heap bad node"; break;
case _HEAPEMPTY: pMemRecordThis->pszStatus = "heap empty"; break;
case _HEAPOK: pMemRecordThis->pszStatus = "OK"; break;
}
sprintf(pMemRecordThis->szAddress, "0x%lX", pMemRecordThis->pObject);
strhcpy(pMemRecordThis->szSource,
(pMemRecordThis->filename)
? pMemRecordThis->filename
: "?"); */
pMemRecordThis = (PMEMRECORD)pMemRecordThis->recc.preccNextRecord;
pHeapItem = (PHEAPITEM)treeNext((TREE*)pHeapItem);
}
cnrhInsertRecords(hwndCnr,
NULL, // parent
(PRECORDCORE)pMemRecordFirst,
TRUE,
NULL,
CRA_RECORDREADONLY,
cHeapItems);
}
}
}
CATCH(excpt1)
{
if (G_pMemdLogFunc)
{
CHAR szMsg[1000];
sprintf(szMsg,
"Crash occured at object #%d out of %d",
cHeapItems,
G_cHeapItems);
G_pMemdLogFunc(szMsg);
}
} END_CATCH();
if (fLocked)
memdUnlock();
}
/*
*@@ mnu_fnCompareIndex:
*
*@@added V0.9.1 (99-12-03) [umoeller]
*/
static SHORT EXPENTRY mnu_fnCompareIndex(PMEMRECORD pmrc1, PMEMRECORD pmrc2, PVOID pStorage)
{
pStorage = pStorage; // to keep the compiler happy
if ((pmrc1) && (pmrc2))
if (pmrc1->ulIndex < pmrc2->ulIndex)
return (-1);
else if (pmrc1->ulIndex > pmrc2->ulIndex)
return (1);
return (0);
}
/*
*@@ mnu_fnCompareSourceFile:
*
*@@added V0.9.1 (99-12-03) [umoeller]
*/
static SHORT EXPENTRY mnu_fnCompareSourceFile(PMEMRECORD pmrc1, PMEMRECORD pmrc2, PVOID pStorage)
{
HAB habDesktop = WinQueryAnchorBlock(HWND_DESKTOP);
pStorage = pStorage; // to keep the compiler happy
if ((pmrc1) && (pmrc2))
switch (WinCompareStrings(habDesktop, 0, 0,
pmrc1->szSource,
pmrc2->szSource,
0))
{
case WCS_LT: return (-1);
case WCS_GT: return (1);
default: // equal
if (pmrc1->ulLine < pmrc2->ulLine)
return (-1);
else if (pmrc1->ulLine > pmrc2->ulLine)
return (1);
}
return (0);
}
/*
*@@ mnu_fnCompareSourceFile:
*
*@@added V0.9.6 (2000-11-12) [umoeller]
*/
static SHORT EXPENTRY mnu_fnCompareSize(PMEMRECORD pmrc1, PMEMRECORD pmrc2, PVOID pStorage)
{
pStorage = pStorage; // to keep the compiler happy
if ((pmrc1) && (pmrc2))
{
if (pmrc1->ulSize > pmrc2->ulSize)
return (1);
else if (pmrc1->ulSize < pmrc2->ulSize)
return (-1);
}
return (0);
}
/*
*@@ mnu_fnCompareAddress:
*
*@@added V0.9.14 (2001-08-01) [umoeller]
*/
static SHORT EXPENTRY mnu_fnCompareAddress(PMEMRECORD pmrc1, PMEMRECORD pmrc2, PVOID pStorage)
{
pStorage = pStorage; // to keep the compiler happy
if ((pmrc1) && (pmrc2))
{
if (pmrc1->ulAddress > pmrc2->ulAddress)
return (1);
else if (pmrc1->ulAddress < pmrc2->ulAddress)
return (-1);
}
return (0);
}
#define ID_MEMCNR 1000
/*
*@@ memd_fnwpMemDebug:
* client window proc for the heap debugger window
* accessible from the Desktop context menu if
* __XWPMEMDEBUG__ is defined. Otherwise, this is not
* compiled.
*
* Usage: this is a regular PM client window procedure
* to be used with WinRegisterClass and WinCreateStdWindow.
* See dtpMenuItemSelected, which uses this.
*
* This creates a container with all the memory objects
* with the size of the client area in turn.
*
*@@added V0.9.1 (99-12-04) [umoeller]
*@@changed V0.9.14 (2001-08-01) [umoeller]: added sort by address
*/
MRESULT EXPENTRY memd_fnwpMemDebug(HWND hwndClient, ULONG msg, MPARAM mp1, MPARAM mp2)
{
MRESULT mrc = 0;
switch (msg)
{
case WM_CREATE:
{
TRY_LOUD(excpt1)
{
// PCREATESTRUCT pcs = (PCREATESTRUCT)mp2;
HWND hwndCnr;
hwndCnr = WinCreateWindow(hwndClient, // parent
WC_CONTAINER,
"",
WS_VISIBLE | CCS_MINIICONS | CCS_READONLY | CCS_SINGLESEL,
0, 0, 0, 0,
hwndClient, // owner
HWND_TOP,
ID_MEMCNR,
NULL, NULL);
if (hwndCnr)
{
XFIELDINFO xfi[11];
PFIELDINFO pfi = NULL;
PMEMRECORD pMemRecordFirst;
int i = 0;
ULONG ulTotalItems = 0,
ulAllocatedItems = 0,
ulFreedItems = 0;
ULONG ulTotalBytes = 0,
ulAllocatedBytes = 0,
ulFreedBytes = 0;
// set up cnr details view
xfi[i].ulFieldOffset = FIELDOFFSET(MEMRECORD, ulIndex);
xfi[i].pszColumnTitle = "No.";
xfi[i].ulDataType = CFA_ULONG;
xfi[i++].ulOrientation = CFA_RIGHT;
xfi[i].ulFieldOffset = FIELDOFFSET(MEMRECORD, cdateAllocated);
xfi[i].pszColumnTitle = "Date";
xfi[i].ulDataType = CFA_DATE;
xfi[i++].ulOrientation = CFA_LEFT;
xfi[i].ulFieldOffset = FIELDOFFSET(MEMRECORD, ctimeAllocated);
xfi[i].pszColumnTitle = "Time";
xfi[i].ulDataType = CFA_TIME;
xfi[i++].ulOrientation = CFA_LEFT;
xfi[i].ulFieldOffset = FIELDOFFSET(MEMRECORD, pszFreed);
xfi[i].pszColumnTitle = "Freed";
xfi[i].ulDataType = CFA_STRING;
xfi[i++].ulOrientation = CFA_CENTER;
xfi[i].ulFieldOffset = FIELDOFFSET(MEMRECORD, ulTID);
xfi[i].pszColumnTitle = "TID";
xfi[i].ulDataType = CFA_ULONG;
xfi[i++].ulOrientation = CFA_RIGHT;
xfi[i].ulFieldOffset = FIELDOFFSET(MEMRECORD, pszFunction);
xfi[i].pszColumnTitle = "Function";
xfi[i].ulDataType = CFA_STRING;
xfi[i++].ulOrientation = CFA_LEFT;
xfi[i].ulFieldOffset = FIELDOFFSET(MEMRECORD, pszSource);
xfi[i].pszColumnTitle = "Source";
xfi[i].ulDataType = CFA_STRING;
xfi[i++].ulOrientation = CFA_LEFT;
xfi[i].ulFieldOffset = FIELDOFFSET(MEMRECORD, ulLine);
xfi[i].pszColumnTitle = "Line";
xfi[i].ulDataType = CFA_ULONG;
xfi[i++].ulOrientation = CFA_RIGHT;
xfi[i].ulFieldOffset = FIELDOFFSET(MEMRECORD, ulSize);
xfi[i].pszColumnTitle = "Size";
xfi[i].ulDataType = CFA_ULONG;
xfi[i++].ulOrientation = CFA_RIGHT;
xfi[i].ulFieldOffset = FIELDOFFSET(MEMRECORD, pszAddress);
xfi[i].pszColumnTitle = "Address";
xfi[i].ulDataType = CFA_STRING;
xfi[i++].ulOrientation = CFA_LEFT;
pfi = cnrhSetFieldInfos(hwndCnr,
&xfi[0],
i, // array item count
TRUE, // no draw lines
3); // return column
{
PSZ pszFont = "9.WarpSans";
WinSetPresParam(hwndCnr,
PP_FONTNAMESIZE,
strlen(pszFont),
pszFont);
}
CreateRecords(hwndCnr,
&ulTotalItems,
&ulAllocatedItems,
&ulFreedItems,
&ulTotalBytes,
&ulAllocatedBytes,
&ulFreedBytes);
BEGIN_CNRINFO()
{
CHAR szCnrTitle[1000];
CHAR szTotalItems[100],
szAllocatedItems[100],
szFreedItems[100],
szReleasedItems[100];
CHAR szTotalBytes[100],
szAllocatedBytes[100],
szFreedBytes[100],
szReleasedBytes[100];
sprintf(szCnrTitle,
"Total memory log entries in use: %s items = %s bytes\n"
" Total memory logs allocated: %s items = %s bytes\n"
" Total memory logs freed: %s items = %s bytes\n"
"Total memory logs freed and discarded: %s items = %s bytes",
nlsThousandsDouble(szTotalItems,
ulTotalItems,
'.'),
nlsThousandsDouble(szTotalBytes,
ulTotalBytes,
'.'),
nlsThousandsDouble(szAllocatedItems,
ulAllocatedItems,
'.'),
nlsThousandsDouble(szAllocatedBytes,
ulAllocatedBytes,
'.'),
nlsThousandsDouble(szFreedItems,
ulFreedItems,
'.'),
nlsThousandsDouble(szFreedBytes,
ulFreedBytes,
'.'),
nlsThousandsDouble(szReleasedItems,
G_ulItemsReleased,
'.'),
nlsThousandsDouble(szReleasedBytes,
G_ulBytesReleased,
'.'));
G_pszMemCnrTitle = strdup(szCnrTitle);
cnrhSetTitle(G_pszMemCnrTitle);
cnrhSetView(CV_DETAIL | CV_MINI | CA_DETAILSVIEWTITLES
| CA_DRAWICON
| CA_CONTAINERTITLE | CA_TITLEREADONLY
| CA_TITLESEPARATOR | CA_TITLELEFT);
cnrhSetSplitBarAfter(pfi);
cnrhSetSplitBarPos(250);
} END_CNRINFO(hwndCnr);
// create menu
G_hwndMemDebugMenu = WinCreateMenu(HWND_DESKTOP,
NULL); // no menu template
winhInsertMenuItem(G_hwndMemDebugMenu,
MIT_END,
1001,
"Sort by index",
MIS_TEXT, 0);
winhInsertMenuItem(G_hwndMemDebugMenu,
MIT_END,
1002,
"Sort by source file",
MIS_TEXT, 0);
winhInsertMenuItem(G_hwndMemDebugMenu,
MIT_END,
1003,
"Sort by object size",
MIS_TEXT, 0);
winhInsertMenuItem(G_hwndMemDebugMenu,
MIT_END,
1004,
"Sort by address",
MIS_TEXT, 0);
WinSetFocus(HWND_DESKTOP, hwndCnr);
}
}
CATCH(excpt1) {} END_CATCH();
mrc = WinDefWindowProc(hwndClient, msg, mp1, mp2);
break; }
case WM_WINDOWPOSCHANGED:
{
PSWP pswp = (PSWP)mp1;
mrc = WinDefWindowProc(hwndClient, msg, mp1, mp2);
if (pswp->fl & SWP_SIZE)
{
WinSetWindowPos(WinWindowFromID(hwndClient, ID_MEMCNR), // cnr
HWND_TOP,
0, 0, pswp->cx, pswp->cy,
SWP_SIZE | SWP_MOVE | SWP_SHOW);
}
break; }
case WM_CONTROL:
{
USHORT usItemID = SHORT1FROMMP(mp1),
usNotifyCode = SHORT2FROMMP(mp1);
if (usItemID == ID_MEMCNR) // cnr
{
switch (usNotifyCode)
{
case CN_CONTEXTMENU:
{
PMEMRECORD precc = (PMEMRECORD)mp2;
if (precc == NULL)
{
// whitespace:
cnrhShowContextMenu(WinWindowFromID(hwndClient, ID_MEMCNR),
NULL, // record
G_hwndMemDebugMenu,
hwndClient);
}
}
}
}
break; }
case WM_COMMAND:
switch (SHORT1FROMMP(mp1))
{
case 1001: // sort by index
WinSendMsg(WinWindowFromID(hwndClient, ID_MEMCNR),
CM_SORTRECORD,
(MPARAM)mnu_fnCompareIndex,
0);
break;
case 1002: // sort by source file
WinSendMsg(WinWindowFromID(hwndClient, ID_MEMCNR),
CM_SORTRECORD,
(MPARAM)mnu_fnCompareSourceFile,
0);
break;
case 1003: // sort by object size
WinSendMsg(WinWindowFromID(hwndClient, ID_MEMCNR),
CM_SORTRECORD,
(MPARAM)mnu_fnCompareSize,
0);
break;
case 1004: // sort by address V0.9.14 (2001-08-01) [umoeller]
WinSendMsg(WinWindowFromID(hwndClient, ID_MEMCNR),
CM_SORTRECORD,
(MPARAM)mnu_fnCompareAddress,
0);
break;
}
break;
case WM_CLOSE:
WinDestroyWindow(WinWindowFromID(hwndClient, ID_MEMCNR));
WinDestroyWindow(WinQueryWindow(hwndClient, QW_PARENT));
free(G_pszMemCnrTitle);
WinDestroyWindow(G_hwndMemDebugMenu);
G_pszMemCnrTitle = NULL;
break;
default:
mrc = WinDefWindowProc(hwndClient, msg, mp1, mp2);
}
return mrc;
}
/*
*@@ memdCreateMemDebugWindow:
* creates a heap debugging window which
* is a standard frame with a container,
* listing all heap objects ever allocated.
*
* The client of this standard frame is in
* memd_fnwpMemDebug.
*
* This thing lists all calls to malloc()
* which were ever made, including the
* source file and source line number which
* made the call. Extreeeemely useful for
* detecting memory leaks.
*
* This only works if the memory functions
* have been replaced with the debug versions
* in this file.
*/
VOID memdCreateMemDebugWindow(VOID)
{
ULONG flStyle = FCF_TITLEBAR | FCF_SYSMENU | FCF_HIDEMAX
| FCF_SIZEBORDER | FCF_SHELLPOSITION
| FCF_NOBYTEALIGN | FCF_TASKLIST;
if (WinRegisterClass(WinQueryAnchorBlock(HWND_DESKTOP),
"XWPMemDebug",
memd_fnwpMemDebug, 0L, 0))
{
HWND hwndClient;
HWND hwndMemFrame = WinCreateStdWindow(HWND_DESKTOP,
0L,
&flStyle,
"XWPMemDebug",
"Allocated XWorkplace Memory Objects",
0L,
NULLHANDLE, // resource
0,
&hwndClient);
if (hwndMemFrame)
{
WinSetWindowPos(hwndMemFrame,
HWND_TOP,
0, 0, 0, 0,
SWP_ZORDER | SWP_SHOW | SWP_ACTIVATE);
}
}
}
#else
void memdDummy2(void)
{
int i = 0;
i++;
}
#endif