home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
xwplascr.zip
/
XWPL0208.ZIP
/
tools
/
xpstat
/
xpstat.c
< prev
next >
Wrap
C/C++ Source or Header
|
2002-04-13
|
59KB
|
1,736 lines
/*
* xpstat.c:
* this is the main (and only) .C file for xpstat.exe.
*
* 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 INCL_WIN
#define INCL_WINWORKPLACE
#define INCL_DOS
#define INCL_DOSERRORS
#include <os2.h>
#include <stdio.h>
#include "setup.h"
#include "helpers\pmprintf.h"
#include "helpers\comctl.h"
#include "helpers\cnrh.h"
#include "helpers\dosh.h"
#include "helpers\exeh.h"
#include "helpers\gpih.h"
#include "helpers\linklist.h"
#include "helpers\memdebug.h"
#include "helpers\procstat.h"
#include "helpers\dosh.h"
#include "helpers\stringh.h"
#include "helpers\textview.h" // PM text view control
#include "helpers\winh.h"
#include "helpers\xstring.h"
#include "dlgids.h"
#include "xpstat.h"
/*
if (fl & PAG_COMMIT)
strcat(szInfo, "commit ");
if (fl & PAG_SHARED)
strcat(szInfo, "shared ");
if (fl & PAG_FREE)
strcat(szInfo, "free ");
if (fl & PAG_BASE)
strcat(szInfo, "base ");
if (fl & PAG_READ)
strcat(szInfo, "read ");
if (fl & PAG_WRITE)
strcat(szInfo, "write ");
if (fl & PAG_EXECUTE)
strcat(szInfo, "exec ");
if (fl & PAG_GUARD)
strcat(szInfo, "guard ");
*/
/* ******************************************************************
*
* Global variables
*
********************************************************************/
HAB G_hab;
HMQ G_hmq;
HWND G_hwndMain = NULLHANDLE;
HMODULE G_hmodNLS = NULLHANDLE;
HWND G_hwndProcListCnr = NULLHANDLE,
G_hwndProcView = NULLHANDLE,
G_hwndSplit = NULLHANDLE,
G_hMainMenu = NULLHANDLE;
const char *pcszClientClass = "ProcInfoClient";
const char *INIAPP = "XWorkplace";
const char *INIKEY_MAINWINPOS = "WndPosXpstat";
ULONG G_ulCurrentView = ID_XPSMI_PIDTREE;
PQTOPLEVEL32 G_pInfo = NULL;
PRECORDCORE G_precSelected = NULL;
BOOL G_fWordWrap = FALSE;
QPROCESS32 SysInitProcess =
{
1, // rectype
NULL, // pThreads
1, // PID
0, // PPID
0, // FS
0, // state
0, // SID
NULLHANDLE, // hmod
0, // thread count
0, // ulPrivSem32Count;
0, // _reserved2_; // 0 always
0, // usSem16Count; // count of 16-bit semaphores in pausSem16 array
0, // usModuleCount; // count of DLLs owned by this process
0, // usShrMemCount; // count of shared memory items
0, // usFdsCount; // count of open files; this is mostly way too large
0, // pausSem16; // ptr to array of 16-bit semaphore handles;
0, // pausModules; // ptr to array of modules;
0, // pausShrMems; // ptr to array of shared mem items;
0, // pausFds; // ptr to array of file handles;
};
/* ******************************************************************
*
* Miscellaneous
*
********************************************************************/
/*
*@@ fnComparePID:
* compare process IDs. Works with PROCRECORD's only.
*/
SHORT EXPENTRY fnComparePID(PPROCRECORD p1, PPROCRECORD p2, PVOID pStorage)
{
if (p1->pProcess && p2->pProcess)
{
if (p1->pProcess->usPID < p2->pProcess->usPID)
return (-1);
else if (p1->pProcess->usPID > p2->pProcess->usPID)
return (1);
}
return (0);
}
/*
*@@ fnCompareSID:
* compare session IDs. Works with PROCRECORD's only.
*/
SHORT EXPENTRY fnCompareSID(PPROCRECORD p1, PPROCRECORD p2, PVOID pStorage)
{
if (p1->pProcess && p2->pProcess)
{
if (p1->pProcess->ulScreenGroupID < p2->pProcess->ulScreenGroupID)
return (-1);
else if (p1->pProcess->ulScreenGroupID > p2->pProcess->ulScreenGroupID)
return (1);
}
return (0);
}
/*
*@@ fnComparePSZ:
* compare record titles. Works with all RECORDCORE's.
*/
SHORT EXPENTRY fnComparePSZ(PRECORDCORE p1, PRECORDCORE p2, PVOID pStorage)
{
if (p1->pszIcon && p2->pszIcon)
{
switch (WinCompareStrings(G_hab,
0, 0,
p1->pszIcon,
p2->pszIcon,
0))
{
case WCS_LT: return (-1);
case WCS_GT: return (1);
}
}
return (0);
}
/*
*@@ SetupWindows:
*
*/
VOID SetupWindows(HWND hwndClient)
{
SPLITBARCDATA sbcd;
XTEXTVIEWCDATA xtxvCData;
XFMTPARAGRAPH fmtp;
G_hwndProcListCnr = WinCreateWindow(hwndClient,
WC_CONTAINER,
"",
WS_VISIBLE,
0, 0, 100, 100,
hwndClient,
HWND_TOP,
ID_PROCLISTCNR,
0,
0);
memset(&xtxvCData, 0, sizeof(xtxvCData));
xtxvCData.cbData = sizeof(xtxvCData);
xtxvCData.flStyle = XTXF_HSCROLL | XTXF_VSCROLL
| XTXF_AUTOHHIDE | XTXF_AUTOVHIDE;
xtxvCData.ulXBorder = 20;
xtxvCData.ulYBorder = 20;
G_hwndProcView = WinCreateWindow(hwndClient,
WC_XTEXTVIEW,
"",
WS_VISIBLE,
0, 0, 100, 100,
hwndClient,
HWND_TOP,
ID_PROCINFO,
&xtxvCData,
0);
winhSetWindowFont(G_hwndProcView, "10.System VIO");
// change default format
WinSendMsg(G_hwndProcView,
TXM_QUERYPARFORMAT,
(MPARAM)0, // default format
(MPARAM)&fmtp);
fmtp.fWordWrap = FALSE;
fmtp.lLeftMargin = 0;
fmtp.lFirstLineMargin = 5;
WinSendMsg(G_hwndProcView,
TXM_SETPARFORMAT,
(MPARAM)0, // default format
(MPARAM)&fmtp);
winhSetWindowFont(G_hwndProcListCnr, "9.WarpSans");
sbcd.ulSplitWindowID = ID_PROCSPLIT;
sbcd.ulCreateFlags = SBCF_VERTICAL | SBCF_PERCENTAGE | SBCF_3DSUNK | SBCF_MOVEABLE;
sbcd.lPos = 50;
sbcd.ulLeftOrBottomLimit = 100;
sbcd.ulRightOrTopLimit = 100;
sbcd.hwndParentAndOwner = hwndClient;
G_hwndSplit = ctlCreateSplitWindow(G_hab,
&sbcd);
// fnwpProcInfoClient,
WinSendMsg(G_hwndSplit,
SPLM_SETLINKS,
(MPARAM)G_hwndProcListCnr,
(MPARAM)G_hwndProcView);
WinSetFocus(HWND_DESKTOP, G_hwndProcListCnr);
}
/*
*@@ SetupMenu:
*
*/
VOID SetupMenu(VOID)
{
WinCheckMenuItem(G_hMainMenu,
G_ulCurrentView,
TRUE);
WinCheckMenuItem(G_hMainMenu,
ID_XPSMI_WORDWRAP,
G_fWordWrap);
}
/*
*@@ AppendModuleInfo:
*
*/
VOID AppendModuleInfo(PXSTRING ppszCurrentInfo,
PSZ pszModuleName)
{
CHAR szTemp[2000];
PSZ pszTemp = szTemp;
PEXECUTABLE pExec = NULL;
PSZ pszExeFormat = "unknown",
psz32Bits = "unknown",
pszVersion = "not available",
pszVendor = "not available",
pszDescr = "not available";
// get module info
if (exehOpen(pszModuleName,
&pExec)
== NO_ERROR)
{
switch (pExec->ulExeFormat)
{
case EXEFORMAT_OLDDOS:
pszExeFormat = "Old DOS";
break;
case EXEFORMAT_NE:
pszExeFormat = "New Executable (NE)";
break;
case EXEFORMAT_PE:
pszExeFormat = "Portable Executable (PE)";
break;
case EXEFORMAT_LX:
pszExeFormat = "Linear Executable (LX)";
break;
case EXEFORMAT_TEXT_BATCH:
pszExeFormat = "Text batch file";
break;
case EXEFORMAT_TEXT_CMD:
pszExeFormat = "Text command file";
break;
}
if (pExec->f32Bits)
psz32Bits = "yes";
else
psz32Bits = "no";
if (exehQueryBldLevel(pExec) == NO_ERROR)
{
if (pExec->pszVendor)
pszVendor = pExec->pszVendor;
if (pExec->pszVersion)
pszVersion = pExec->pszVersion;
if (pExec->pszInfo)
pszDescr = pExec->pszInfo;
}
}
pszTemp = szTemp;
pszTemp += sprintf(pszTemp, "Module format: %s\n", pszExeFormat);
pszTemp += sprintf(pszTemp, "32-bit module: %s\n", psz32Bits);
pszTemp += sprintf(pszTemp, "Vendor: %s\n", pszVendor);
pszTemp += sprintf(pszTemp, "Version: %s\n", pszVersion);
xstrcat(ppszCurrentInfo, szTemp, 0);
pszTemp = szTemp;
pszTemp += sprintf(pszTemp, "Description: %s\n", pszDescr);
xstrcat(ppszCurrentInfo, szTemp, 0);
if (pExec)
exehClose(&pExec);
}
/* ******************************************************************
*
* "Process list" mode
*
********************************************************************/
/*
*@@ InsertProcessList:
* clears the container and inserts all processes by PID.
* Gets called by RefreshView().
*/
VOID InsertProcessList(HWND hwndCnr,
BOOL fSortBySID) // in: else PID
{
APIRET arc = NO_ERROR;
XFIELDINFO axfi[2];
ULONG i = 0;
WinSendMsg(hwndCnr,
CM_REMOVERECORD,
(MPARAM)NULL,
MPFROM2SHORT(0, // all records
CMA_FREE | CMA_INVALIDATE));
BEGIN_CNRINFO()
{
cnrhSetView(CV_DETAIL | CA_DETAILSVIEWTITLES);
if (fSortBySID)
{
cnrhSetSortFunc(fnCompareSID);
}
else
cnrhSetSortFunc(fnComparePID);
} END_CNRINFO(G_hwndProcListCnr);
// set up cnr details view
i = 0;
axfi[i].ulFieldOffset = FIELDOFFSET(PROCRECORD, pszPID);
if (fSortBySID)
axfi[i].pszColumnTitle = "SID";
else
axfi[i].pszColumnTitle = "PID";
axfi[i].ulDataType = CFA_STRING;
axfi[i++].ulOrientation = CFA_LEFT;
axfi[i].ulFieldOffset = FIELDOFFSET(PROCRECORD, pszModuleName);
axfi[i].pszColumnTitle = "Process";
axfi[i].ulDataType = CFA_STRING;
axfi[i++].ulOrientation = CFA_LEFT;
cnrhClearFieldInfos(G_hwndProcListCnr, FALSE); // no invalidate
cnrhSetFieldInfos(G_hwndProcListCnr,
axfi,
i,
TRUE,
0);
if (G_pInfo)
{
prc32FreeInfo(G_pInfo);
G_pInfo = NULL;
}
G_pInfo = prc32GetInfo(&arc);
if (G_pInfo)
{
PQPROCESS32 pProcess = G_pInfo->pProcessData;
PPROCRECORD precFirst,
precThis;
ULONG cProcesses = 0;
pProcess = G_pInfo->pProcessData;
while ((pProcess) && (pProcess->ulRecType == 1))
{
PQTHREAD32 pThread = pProcess->pThreads;
for (i = 0;
i < pProcess->usThreadCount;
i++, pThread++)
;
pProcess = (PQPROCESS32)pThread;
cProcesses++;
}
// insert records
precFirst = (PPROCRECORD)cnrhAllocRecords(hwndCnr,
sizeof(PROCRECORD),
cProcesses);
pProcess = G_pInfo->pProcessData;
precThis = precFirst;
while ((pProcess) && (pProcess->ulRecType == 1))
{
PQTHREAD32 pThread = pProcess->pThreads;
for (i = 0;
i < pProcess->usThreadCount;
i++, pThread++)
;
DosQueryModuleName(pProcess->usHModule,
sizeof(precThis->szModuleName),
precThis->szModuleName);
if (fSortBySID)
sprintf(precThis->szPID, "0x%04lX", pProcess->ulScreenGroupID);
else
sprintf(precThis->szPID, "0x%04lX", pProcess->usPID);
precThis->pszPID = precThis->szPID;
sprintf(precThis->szTitle, "%s: %s",
precThis->szPID,
precThis->szModuleName);
precThis->pszModuleName = precThis->szModuleName;
precThis->recc.pszIcon
= precThis->recc.pszTree
= precThis->recc.pszName
= precThis->recc.pszText
= precThis->szTitle;
precThis->pProcess = pProcess;
pProcess = (PQPROCESS32)pThread;
precThis = (PPROCRECORD)precThis->recc.preccNextRecord;
}
cnrhInsertRecords(hwndCnr,
NULL, // parent recc
(PRECORDCORE)precFirst,
TRUE,
NULL,
CRA_RECORDREADONLY,
cProcesses);
}
}
/*
*@@ DescribeSem32:
*
*@@added V0.9.10 (2001-04-08) [umoeller]
*/
VOID DescribeSem32(PSZ pszTemp,
PQS32SEM32 pSem32)
{
pszTemp += sprintf(pszTemp,
" %06lX %8lX %04d",
pSem32->ulHandle,
pSem32->ulBlockID,
pSem32->fl);
if (pSem32->fl & QS32_DC_SEM_SHARED)
pszTemp += sprintf(pszTemp, " shared");
/* if (pSem32->fl & QS32_DC_SEM_PM)
pszTemp += sprintf(pszTemp, " PM"); */
if (pSem32->fl & QS32_DCM_MUTEX_SEM)
pszTemp += sprintf(pszTemp, " mutex");
if (pSem32->fl & QS32_DCE_EVENT_SEM)
pszTemp += sprintf(pszTemp, " event");
if (pSem32->fl & QS32_DCMW_MUX_SEM)
pszTemp += sprintf(pszTemp, " muxwait");
if (pSem32->fl & QS32_DCE_POSTONE)
pszTemp += sprintf(pszTemp, ", post-one");
if (pSem32->fl & QS32_DCE_AUTORESET)
pszTemp += sprintf(pszTemp, ", auto-reset");
if (pSem32->fl & QS32_DCMW_WAIT_ANY)
pszTemp += sprintf(pszTemp, ", waitAny");
if (pSem32->fl & QS32_DCMW_WAIT_ALL)
pszTemp += sprintf(pszTemp, ", waitAll");
if (pSem32->fl & QS32_DE_POSTED)
pszTemp += sprintf(pszTemp, ", %dx posted ", pSem32->usPostCount);
if (pSem32->fl & QS32_DM_OWNER_DIED)
pszTemp += sprintf(pszTemp, ", owner died");
if (pSem32->fl & QS32_DMW_MTX_MUX)
pszTemp += sprintf(pszTemp, ", contains mutexes");
if (pSem32->fl & QS32_DE_16BIT_MW)
pszTemp += sprintf(pszTemp, ", part of 16-bit muxwait");
if (pSem32->fl & QS32_DHO_SEM_OPEN)
pszTemp += sprintf(pszTemp, ", opened by device driver");
if (pSem32->pszName)
pszTemp += sprintf(pszTemp,
"\n name: \"%s\"",
pSem32->pszName);
if (pSem32->pvDeviceDriver)
pszTemp += sprintf(pszTemp,
"\n ptr: %08lX",
pSem32->pvDeviceDriver);
/* if (pSem32->us_)
pszTemp += sprintf(pszTemp,
"\n strange us_: %04lX",
pSem32->us_);
if (pSem32->ulElse)
pszTemp += sprintf(pszTemp,
"\n else: %08lX",
pSem32->ulElse);
if (pSem32->ulElse2)
pszTemp += sprintf(pszTemp,
"\n else2: %08lX",
pSem32->ulElse2); */
strcpy(pszTemp, "\n");
}
/*
*@@ ProcessSelected:
* gets called when a new process gets selected
* to compose the process information string
* displayed on the right.
*/
VOID ProcessSelected(VOID)
{
XSTRING strCurrentInfo;
xstrInit(&strCurrentInfo, 1000);
strCurrentInfo.ulDelta = 1000;
if (G_precSelected)
{
PQPROCESS32 pProcess = ((PPROCRECORD)G_precSelected)->pProcess;
PQTHREAD32 pThread;
PSZ pszSessionType = "unknown";
CHAR szTemp[2000],
szTemp2[200] = "";
PSZ pszTemp = szTemp;
ULONG i,
cMsgQueues = 0;
pszTemp += sprintf(pszTemp, "PID: 0x%04lX\n", pProcess->usPID);
pszTemp += sprintf(pszTemp, "Parent PID: 0x%04lX\n", pProcess->usPPID);
pszTemp += sprintf(pszTemp, "Screen Group ID: 0x%04lX\n", pProcess->ulScreenGroupID);
pszTemp += sprintf(pszTemp, "\nModule: %s\n", ((PPROCRECORD)G_precSelected)->szModuleName);
xstrcpy(&strCurrentInfo, szTemp, 0);
if (pProcess->usPID == 1)
{
// sysinit:
xstrcat(&strCurrentInfo, "\nKernel pseudo-process.\n", 0);
}
else
{
// regular process:
AppendModuleInfo(&strCurrentInfo,
((PPROCRECORD)G_precSelected)->szModuleName);
// get process type
switch (pProcess->ulProgType)
{
case 0:
pszSessionType = "Full screen protected mode";
break;
case 1:
pszSessionType = "Real mode (probably VDM)";
break;
case 2:
pszSessionType = "VIO windowable protected mode";
break;
case 3:
pszSessionType = "Presentation manager protected mode";
break;
case 4:
pszSessionType = "Detached protected mode";
break;
}
pszTemp = szTemp;
pszTemp += sprintf(pszTemp, "\nProcess type: %d (%s)\n",
pProcess->ulProgType,
pszSessionType);
if (pProcess->ulState & STAT_EXITLIST)
strcpy(szTemp2, "[processing exit list] ");
if (pProcess->ulState & STAT_EXIT1)
strcat(szTemp2, "[exiting thread 1] ");
if (pProcess->ulState & STAT_EXITALL)
strcat(szTemp2, "[exiting all] ");
if (pProcess->ulState & STAT_PARSTAT)
strcat(szTemp2, "[notify parent on exit] ");
if (pProcess->ulState & STAT_SYNCH)
strcat(szTemp2, "[parent waiting on exit] ");
if (pProcess->ulState & STAT_DYING)
strcat(szTemp2, "[dying] ");
if (pProcess->ulState & STAT_EMBRYO)
strcat(szTemp2, "[embryo] ");
pszTemp += sprintf(pszTemp, "\nulState: 0x%lX %s\n",
pProcess->ulState,
szTemp2);
// threads
pszTemp += sprintf(pszTemp, "\nThreads: %d\n", pProcess->usThreadCount);
// header for the following
pszTemp += sprintf(pszTemp, " TID Slot SleepID Prty State HMQ==PMQ\n");
xstrcat(&strCurrentInfo, szTemp, 0);
// dump threads
pThread = pProcess->pThreads;
for (i = 0;
i < pProcess->usThreadCount;
i++, pThread++)
{
CHAR szState[30] = "block";
HAB habhmq = 0;
HMQ hmq = 0;
switch(pThread->ucState)
{
case 1: strcpy(szState, "ready"); break;
case 5: strcpy(szState, "runng"); break;
case 9: strcpy(szState, "loadd"); break;
}
pszTemp = szTemp;
pszTemp += sprintf(pszTemp,
" %02d %04lX %08lX %04lX %s ",
pThread->usTID,
pThread->usSlotID,
pThread->ulSleepID,
pThread->ulPriority,
szState);
if (hmq = winhFindMsgQueue(pProcess->usPID,
pThread->usTID,
&habhmq))
{
pszTemp += sprintf(pszTemp, "0x%lX", hmq);
cMsgQueues++;
}
pszTemp += sprintf(pszTemp, "\n");
xstrcat(&strCurrentInfo, szTemp, 0);
}
// dump message queues
if (cMsgQueues)
{
HENUM henum = WinBeginEnumWindows(HWND_OBJECT);
HWND hwndThis;
pszTemp = szTemp;
pszTemp += sprintf(pszTemp, "\nMessage queues: %d\n", cMsgQueues);
// header for the following
pszTemp += sprintf(pszTemp, " PMQ HWND TID size\n");
xstrcat(&strCurrentInfo, szTemp, 0);
while (hwndThis = WinGetNextWindow(henum))
{
CHAR szClass[200];
if (WinQueryClassName(hwndThis, sizeof(szClass), szClass))
{
if (strcmp(szClass, "#32767") == 0)
{
// is message queue:
PID pidWin = 0;
TID tidWin = 0;
WinQueryWindowProcess(hwndThis,
&pidWin,
&tidWin);
if (pidWin == pProcess->usPID)
{
// is our process:
// get message queue for this
HMQ hmq = WinQueryWindowULong(hwndThis, QWL_HMQ);
MQINFO mqi = {0};
ULONG cb, fl;
WinQueryQueueInfo(hmq, &mqi, sizeof(mqi));
pszTemp = szTemp;
pszTemp += sprintf(pszTemp, " 0x%08lX 0x%lX %02d %d",
hmq, hwndThis, tidWin, mqi.cmsgs);
pszTemp += sprintf(pszTemp, "\n");
xstrcat(&strCurrentInfo, szTemp, 0);
}
}
}
}
WinEndEnumWindows(henum);
}
// dump public 32-bit semaphores
sprintf(szTemp, "\nPublic 32-bit semaphores:\n");
xstrcat(&strCurrentInfo, szTemp, 0);
if (!G_pInfo->pSem32Data)
xstrcat(&strCurrentInfo, " cannot get data\n", 0);
else
{
// semaphore data available:
PQS32SEM32 pFirst = G_pInfo->pSem32Data,
pSem32 = pFirst;
ULONG ul;
xstrcat(&strCurrentInfo,
" handle blockid flags name\n", 0);
while (pSem32)
{
DescribeSem32(szTemp, pSem32);
xstrcat(&strCurrentInfo, szTemp, 0);
pSem32 = pSem32->pNext;
}
}
// dump private 32-bit semaphores
sprintf(szTemp, "\nPrivate 32-bit semaphores: %d\n", pProcess->ulPrivSem32Count);
xstrcat(&strCurrentInfo, szTemp, 0);
if (!pProcess->pvPrivSem32s)
xstrcat(&strCurrentInfo, " cannot get data\n", 0);
else
{
// semaphore data available:
PQS32SEM32 pFirst = (PQS32SEM32)pProcess->pvPrivSem32s,
pSem32 = pFirst;
ULONG ul;
xstrcat(&strCurrentInfo,
" handle blockid flags name\n", 0);
for (ul = 0;
ul < pProcess->ulPrivSem32Count;
ul++)
{
DescribeSem32(szTemp, pSem32);
xstrcat(&strCurrentInfo, szTemp, 0);
pSem32 = pSem32->pNext;
}
}
// dump 16-bit semaphores
sprintf(szTemp, "\n16-bit semaphores: %d\n", pProcess->usSem16Count);
xstrcat(&strCurrentInfo, szTemp, 0);
if (pProcess->usSem16Count)
{
sprintf(szTemp, " indx ownr flag cUse cReq \n", pProcess->usSem16Count);
xstrcat(&strCurrentInfo, szTemp, 0);
for (i = 0;
i < pProcess->usSem16Count;
i++)
{
USHORT usSemThis = pProcess->pausSem16[i];
PQS32SEM16 pSem16 = prc32FindSem16(G_pInfo, usSemThis);
pszTemp = szTemp;
pszTemp += sprintf(pszTemp, " %4d", usSemThis);
if (pSem16)
pszTemp += sprintf(pszTemp,
" %04lX %04lX %04lX %04lX S%s",
pSem16->usSysSemOwner,
pSem16->fsSysSemFlags,
pSem16->usSysSemRefCnt,
pSem16->usSysSemProcCnt,
pSem16->szName);
strcat(pszTemp, "\n");
xstrcat(&strCurrentInfo, szTemp, 0);
}
}
// dump shared memory
sprintf(szTemp, "\nShared mem: %d references\n", pProcess->usShrMemCount);
xstrcat(&strCurrentInfo, szTemp, 0);
if (pProcess->usShrMemCount)
{
sprintf(szTemp, " shrmID selector cRef\n");
xstrcat(&strCurrentInfo, szTemp, 0);
for (i = 0;
i < pProcess->usShrMemCount;
i++)
{
USHORT usShrThis = pProcess->pausShrMems[i];
PQSHRMEM32 pShrThis = prc32FindShrMem(G_pInfo, usShrThis);
pszTemp = szTemp;
pszTemp += sprintf(pszTemp, " 0x%04lX", usShrThis);
if (pShrThis)
pszTemp += sprintf(pszTemp, " 0x%04lX %6d %s",
pShrThis->usSelector,
pShrThis->usRefCount,
pShrThis->acName);
strcat(pszTemp, "\n");
xstrcat(&strCurrentInfo, szTemp, 0);
}
}
// dump modules
sprintf(szTemp, "\nModule references (imports): %d\n", pProcess->usModuleCount);
xstrcat(&strCurrentInfo, szTemp, 0);
if (pProcess->usModuleCount)
{
for (i = 0;
i < pProcess->usModuleCount;
i++)
{
pszTemp = szTemp;
pszTemp += sprintf(pszTemp, " 0x%04lX ", pProcess->pausModules[i]);
DosQueryModuleName(pProcess->pausModules[i],
sizeof(szTemp),
pszTemp);
strcat(pszTemp, "\n");
xstrcat(&strCurrentInfo, szTemp, 0);
}
}
// dump open files
sprintf(szTemp, "\nOpen files: %d\n", pProcess->usFdsCount);
xstrcat(&strCurrentInfo, szTemp, 0);
if (pProcess->usFdsCount)
{
xstrcat(&strCurrentInfo,
" sfn cOpn Flags Accs Size hVol attribs\n", 0);
for (i = 0;
i < pProcess->usFdsCount;
i++)
{
USHORT usFileID = pProcess->pausFds[i];
szTemp[0] = 0;
pszTemp = szTemp;
pszTemp += sprintf(pszTemp,
" %04lX",
usFileID);
if (usFileID) // rule out "0" file handles
{
PQFILEDATA32 pFile = prc32FindFileData(G_pInfo, usFileID);
if (pFile) // rule out pseudo-file handles
{
CHAR szAttribs[] = "......";
PSZ pszAccess = szAttribs;
CHAR szSize[20];
PQFDS32 pFileData = pFile->paFiles;
USHORT fsAttribs = pFileData->fsAttribs;
*pszAccess++ = (fsAttribs & 0x20) ? 'A' : '-';
*pszAccess++ = (fsAttribs & 0x10) ? 'D' : '-';
*pszAccess++ = (fsAttribs & 0x08) ? 'L' : '-';
*pszAccess++ = (fsAttribs & 0x04) ? 'S' : '-';
*pszAccess++ = (fsAttribs & 0x02) ? 'H' : '-';
*pszAccess++ = (fsAttribs & 0x01) ? 'R' : '-';
if (pFileData->ulFileSize > (8*1024*1024))
sprintf(szSize, "%4dM", pFileData->ulFileSize / (8*1024*1024));
else if (pFileData->ulFileSize > 1024)
sprintf(szSize, "%4dK", pFileData->ulFileSize / 1024);
else
sprintf(szSize, "%4db", pFileData->ulFileSize);
pszTemp += sprintf(pszTemp,
" %04d %08lx %04x %s %04lX %s ",
pFile->ulCFiles,
pFileData->flFlags,
pFileData->flAccess,
szSize,
pFileData->usHVolume,
szAttribs);
if ((pFileData->flFlags & FSF_NO_SFT_HANDLE_ALLOCTD) == 0)
// we do have a file handle:
pszTemp += sprintf(pszTemp,
"%s",
pFile->szFilename);
else
// no SFT file handle allocated:
strcat(szTemp, " [no SFT handle allocated]");
} // end if (pFile) // rule out pseudo-file handles
else
strcat(szTemp, " [cannot find SFT entry]");
} // end if (usFileID) // rule out "0" file handles
strcat(szTemp, "\n");
xstrcat(&strCurrentInfo, szTemp, 0);
}
}
}
} // end if (G_precSelected)
xstrcat(&strCurrentInfo, "End of dump\n", 0);
WinSetWindowText(G_hwndProcView, strCurrentInfo.psz);
xstrClear(&strCurrentInfo);
}
/* ******************************************************************
*
* "Process tree" mode
*
********************************************************************/
/*
*@@ InsertProcTreeRecord:
*
*/
PPROCRECORD InsertProcTreeRecord(HWND hwndCnr,
PPROCRECORD precParent,
PQPROCESS32 pProcess)
{
PPROCRECORD prec = (PPROCRECORD)cnrhAllocRecords(hwndCnr,
sizeof(PROCRECORD),
1);
if (pProcess->usPID != 1)
DosQueryModuleName(pProcess->usHModule,
sizeof(prec->szModuleName),
prec->szModuleName);
else
strcpy(prec->szModuleName, "[sysinit]");
prec->pszModuleName = prec->szModuleName;
sprintf(prec->szPID, "0x%04lX",
pProcess->usPID);
prec->pszPID = prec->szPID;
sprintf(prec->szTitle, "%s: %s",
prec->szPID,
prec->szModuleName);
prec->recc.pszIcon
= prec->recc.pszTree
= prec->recc.pszName
= prec->recc.pszText
= prec->szTitle;
prec->pProcess = pProcess;
// insert records
cnrhInsertRecords(hwndCnr,
(PRECORDCORE)precParent, // parent recc
(PRECORDCORE)prec,
FALSE,
NULL,
CRA_RECORDREADONLY | CRA_EXPANDED,
1);
return (prec);
}
/*
*@@ InsertProcessesWithParent:
*
*/
VOID InsertProcessesWithParent(HWND hwndCnr,
ULONG ulParentPID, // initially 0
PPROCRECORD precParent)
{
PQPROCESS32 pProcess = G_pInfo->pProcessData;
ULONG i;
/* if (ulParentPID == 0)
{
PPROCRECORD prec = InsertProcTreeRecord(hwndCnr,
NULL,
&SysInitProcess); // "sysinit" process
InsertProcessesWithParent(hwndCnr,
1, // pid of sysinit
prec); // preccParent
} */
while ( (pProcess) && (pProcess->ulRecType == 1) )
{
PQTHREAD32 pThread = pProcess->pThreads;
for (i = 0;
i < pProcess->usThreadCount;
i++, pThread++)
;
if (pProcess->usPPID == ulParentPID)
{
PPROCRECORD prec = InsertProcTreeRecord(hwndCnr,
precParent,
pProcess);
// recurse for processes which have this proc as parent
InsertProcessesWithParent(hwndCnr,
pProcess->usPID,
prec); // preccParent
}
// next process
pProcess = (PQPROCESS32)pThread;
}
}
/*
*@@ InsertProcessTree:
*
*/
VOID InsertProcessTree(HWND hwndCnr)
{
APIRET arc = NO_ERROR;
XFIELDINFO axfi[2];
ULONG i = 0;
WinSendMsg(hwndCnr,
CM_REMOVERECORD,
(MPARAM)NULL,
MPFROM2SHORT(0, // all records
CMA_FREE | CMA_INVALIDATE));
// clear cnr details view
cnrhClearFieldInfos(G_hwndProcListCnr, FALSE); // no invalidate
BEGIN_CNRINFO()
{
cnrhSetView(CV_TREE | CV_TEXT | CA_TREELINE);
cnrhSetSortFunc(fnComparePID);
cnrhSetTreeIndent(20);
} END_CNRINFO(G_hwndProcListCnr);
if (G_pInfo)
{
prc32FreeInfo(G_pInfo);
G_pInfo = NULL;
}
G_pInfo = prc32GetInfo(&arc);
if (G_pInfo)
{
PQPROCESS32 pProcess = G_pInfo->pProcessData;
PPROCRECORD precFirst,
precThis;
ULONG cProcesses = 0;
pProcess = G_pInfo->pProcessData;
while ((pProcess) && (pProcess->ulRecType == 1))
{
PQTHREAD32 pThread = pProcess->pThreads;
for (i = 0;
i < pProcess->usThreadCount;
i++, pThread++)
;
pProcess = (PQPROCESS32)pThread;
cProcesses++;
}
// insert records
InsertProcessesWithParent(hwndCnr,
0,
NULL); // preccParent
cnrhInvalidateAll(hwndCnr);
}
}
/* ******************************************************************
*
* "Module tree" mode
*
********************************************************************/
/*
*@@ InsertModule2Parent:
*
*/
PMODRECORD InsertModule2Parent(HWND hwndCnr,
PQMODULE32 pModule,
PMODRECORD precParent)
{
PSZ p;
PMODRECORD prec = (PMODRECORD)cnrhAllocRecords(hwndCnr,
sizeof(MODRECORD),
1);
DosQueryModuleName(pModule->usHModule,
sizeof(prec->szModuleName),
prec->szModuleName);
prec->pszModuleName = prec->szModuleName;
p = strrchr(prec->szModuleName, '\\');
if (p)
p++;
else
p = prec->szModuleName;
prec->recc.pszIcon
= prec->recc.pszTree
= prec->recc.pszName
= prec->recc.pszText
= p;
prec->pModule = pModule;
// insert records
cnrhInsertRecords(hwndCnr,
(PRECORDCORE)precParent, // parent recc
(PRECORDCORE)prec,
FALSE,
NULL,
CRA_RECORDREADONLY | CRA_COLLAPSED,
1);
return (prec);
}
/*
*@@ InsertModulesTree:
*
*/
VOID InsertModulesTree(HWND hwndCnr)
{
APIRET arc = NO_ERROR;
XFIELDINFO axfi[2];
ULONG i = 0;
WinSendMsg(hwndCnr,
CM_REMOVERECORD,
(MPARAM)NULL,
MPFROM2SHORT(0, // all records
CMA_FREE | CMA_INVALIDATE));
// clear cnr details view
cnrhClearFieldInfos(G_hwndProcListCnr, FALSE); // no invalidate
BEGIN_CNRINFO()
{
cnrhSetView(CV_TREE | CV_TEXT | CA_TREELINE);
cnrhSetSortFunc(fnComparePSZ);
cnrhSetTreeIndent(20);
} END_CNRINFO(G_hwndProcListCnr);
if (G_pInfo)
{
prc32FreeInfo(G_pInfo);
G_pInfo = NULL;
}
G_pInfo = prc32GetInfo(&arc);
if (G_pInfo)
{
PQMODULE32 pModule = G_pInfo->pModuleData;
while (pModule)
{
// insert records; this recurses
InsertModule2Parent(hwndCnr,
pModule,
NULL); // preccParent
pModule = pModule->pNext;
}
}
}
/*
*@@ ModuleSelected:
*
*/
VOID ModuleSelected(VOID)
{
XSTRING strCurrentInfo;
xstrInit(&strCurrentInfo, 40);
if (G_precSelected)
{
PMODRECORD precSelected = (PMODRECORD)G_precSelected;
PQMODULE32 pModule = precSelected->pModule,
pModule2;
PQPROCESS32 pProcess = G_pInfo->pProcessData;
CHAR szTemp[2000],
szTemp2[200] = "";
PSZ pszTemp = szTemp;
ULONG i,
cProcCount = 0;
pszTemp += sprintf(pszTemp, "Module name: %s\n", precSelected->szModuleName);
pszTemp += sprintf(pszTemp, "Module handle: 0x%04lX\n", pModule->usHModule);
xstrcpy(&strCurrentInfo, szTemp, 0);
// module flags
pszTemp = szTemp;
pszTemp += sprintf(pszTemp, "Module flags: 0x%04lX\n", pModule->fFlat);
pszTemp += sprintf(pszTemp, "Segments: %d\n\n", pModule->cObjects);
xstrcat(&strCurrentInfo, szTemp, 0);
// module info
AppendModuleInfo(&strCurrentInfo,
precSelected->szModuleName);
// find processes using this module
pszTemp = szTemp;
pszTemp += sprintf(pszTemp, "\nProcesses using this module directly:\n");
xstrcat(&strCurrentInfo, szTemp, 0);
pProcess = G_pInfo->pProcessData;
while ((pProcess) && (pProcess->ulRecType == 1))
{
PQTHREAD32 pThread = pProcess->pThreads;
if (pProcess->usModuleCount)
{
for (i = 0;
i < pProcess->usModuleCount;
i++)
{
if (pProcess->pausModules[i] == pModule->usHModule)
{
// this proc uses this module:
// store process name
strcpy(szTemp, " ");
DosQueryModuleName(pProcess->usHModule,
sizeof(szTemp) - 4,
szTemp + 4);
strcat(szTemp, "\n");
xstrcat(&strCurrentInfo, szTemp, 0);
cProcCount++;
}
}
}
// next process
for (i = 0;
i < pProcess->usThreadCount;
i++, pThread++)
;
pProcess = (PQPROCESS32)pThread;
}
pszTemp = szTemp;
if (cProcCount == 0)
pszTemp += sprintf(pszTemp, " none\n");
else
pszTemp += sprintf(pszTemp, "Total: %d processes\n", cProcCount);
xstrcat(&strCurrentInfo, szTemp, 0);
// other modules using this module
pszTemp = szTemp;
pszTemp += sprintf(pszTemp, "\nOther modules using this module:\n");
xstrcat(&strCurrentInfo, szTemp, 0);
cProcCount = 0;
pModule2 = G_pInfo->pModuleData;
while (pModule2)
{
if (pModule2->ulRefCount)
{
for (i = 0;
i < pModule2->ulRefCount;
i++)
{
if (pModule2->ausModRef[i] == pModule->usHModule)
{
pszTemp = szTemp;
DosQueryModuleName(pModule2->usHModule,
sizeof(szTemp2),
szTemp2);
pszTemp += sprintf(pszTemp, " 0x%04lX: %s\n",
pModule2->usHModule,
szTemp2);
xstrcat(&strCurrentInfo, szTemp, 0);
cProcCount++;
}
}
}
pModule2 = pModule2->pNext;
}
pszTemp = szTemp;
if (cProcCount == 0)
pszTemp += sprintf(pszTemp, " none\n");
else
pszTemp += sprintf(pszTemp, "Total: %d modules\n", cProcCount);
xstrcat(&strCurrentInfo, szTemp, 0);
// references
pszTemp = szTemp;
pszTemp += sprintf(pszTemp, "\nModule references (imports, inserted into tree): %d\n", pModule->ulRefCount);
xstrcat(&strCurrentInfo, szTemp, 0);
if (pModule->ulRefCount)
{
BOOL fMarkSelected = FALSE;
for (i = 0;
i < pModule->ulRefCount;
i++)
{
pszTemp = szTemp;
DosQueryModuleName(pModule->ausModRef[i],
sizeof(szTemp2),
szTemp2);
pszTemp += sprintf(pszTemp, " 0x%04lX: %s\n",
pModule->ausModRef[i],
szTemp2);
xstrcat(&strCurrentInfo, szTemp, 0);
if ( (!precSelected->fSubModulesInserted)
&& (pModule->ausModRef[i] != pModule->usHModule)
)
{
PQMODULE32 pSubModule = prc32FindModule(G_pInfo,
pModule->ausModRef[i]);
if (pSubModule)
InsertModule2Parent(G_hwndProcListCnr,
pSubModule,
precSelected);
fMarkSelected = TRUE;
}
}
if (fMarkSelected)
precSelected->fSubModulesInserted = TRUE;
}
} // end if (G_precSelected)
xstrcat(&strCurrentInfo, "End of dump\n", 0);
WinSetWindowText(G_hwndProcView, strCurrentInfo.psz);
xstrClear(&strCurrentInfo);
}
/* ******************************************************************
*
* General view stuff
*
********************************************************************/
/*
*@@ RefreshView:
*
*/
VOID RefreshView(VOID)
{
switch (G_ulCurrentView)
{
case ID_XPSMI_PIDLIST:
InsertProcessList(G_hwndProcListCnr, FALSE);
break;
case ID_XPSMI_SIDLIST:
InsertProcessList(G_hwndProcListCnr, TRUE);
break;
case ID_XPSMI_PIDTREE:
InsertProcessTree(G_hwndProcListCnr);
break;
case ID_XPSMI_MODTREE:
InsertModulesTree(G_hwndProcListCnr);
break;
}
}
BOOL APIENTRY PrintCallback(ULONG ulPage,
ULONG ulUser)
{
CHAR szMsg[1000];
sprintf(szMsg, "Page %d. Continue?", ulPage);
if (winhYesNoBox("Printing", szMsg) == MBID_YES)
return (TRUE);
else
return (FALSE);
}
/*
*@@ fnwpProcInfoClient:
*
*/
MRESULT EXPENTRY fnwpProcInfoClient(HWND hwndClient, ULONG msg, MPARAM mp1, MPARAM mp2)
{
MRESULT mrc = 0;
switch (msg)
{
case WM_CREATE:
SetupWindows(hwndClient);
RefreshView();
mrc = (MPARAM)FALSE; // continue;
break;
/*
* WM_WINDOWPOSCHANGED:
*
*/
case WM_WINDOWPOSCHANGED:
{
// this msg is passed two SWP structs: WM_SIZE
// one for the old, one for the new data
// (from PM docs)
PSWP pswpNew = PVOIDFROMMP(mp1);
// PSWP pswpOld = pswpNew + 1;
// resizing?
if (pswpNew->fl & SWP_SIZE)
{
WinSetWindowPos(G_hwndSplit, HWND_TOP,
0, 0,
pswpNew->cx, pswpNew->cy, // sCXNew, sCYNew,
SWP_SIZE);
}
// return default NULL
break; }
case WM_CONTROL:
{
USHORT usID = SHORT1FROMMP(mp1);
USHORT usNotifyCode = SHORT2FROMMP(mp1);
if (usID == ID_PROCLISTCNR)
switch (usNotifyCode)
{
case CN_EMPHASIS:
{
PNOTIFYRECORDEMPHASIS pnre = (PNOTIFYRECORDEMPHASIS)mp2;
if (pnre->pRecord)
if (pnre->pRecord->flRecordAttr & CRA_SELECTED)
{
G_precSelected = pnre->pRecord;
switch (G_ulCurrentView)
{
case ID_XPSMI_PIDLIST:
case ID_XPSMI_SIDLIST:
case ID_XPSMI_PIDTREE:
ProcessSelected();
break;
case ID_XPSMI_MODTREE:
ModuleSelected();
break;
}
}
break; }
}
break; }
case WM_COMMAND:
{
SHORT sCommand = SHORT1FROMMP(mp1);
switch (sCommand)
{
case ID_XPSMI_EXIT:
WinPostMsg(WinQueryWindow(hwndClient, QW_PARENT),
WM_CLOSE,
0, 0);
break;
case ID_XPSMI_PIDLIST:
case ID_XPSMI_SIDLIST:
case ID_XPSMI_PIDTREE:
case ID_XPSMI_MODTREE:
if (G_ulCurrentView != sCommand)
{
WinCheckMenuItem(G_hMainMenu,
G_ulCurrentView,
FALSE);
G_ulCurrentView = sCommand;
RefreshView();
SetupMenu();
}
break;
case ID_XPSMI_REFRESH:
RefreshView(); // InsertProcessList(G_hwndProcListCnr);
break;
case ID_XPSMI_WORDWRAP:
G_fWordWrap = !G_fWordWrap;
SetupMenu();
WinSendMsg(G_hwndProcView,
TXM_SETWORDWRAP,
(MPARAM)G_fWordWrap,
0);
break;
}
break; }
case WM_CHAR:
{
USHORT usFlags = SHORT1FROMMP(mp1);
USHORT usch = SHORT1FROMMP(mp2);
USHORT usvk = SHORT2FROMMP(mp2);
if ( (usFlags & KC_VIRTUALKEY)
&& (usvk == VK_TAB)
)
{
if ((usFlags & KC_KEYUP) == 0)
if (WinQueryFocus(HWND_DESKTOP) == G_hwndProcListCnr)
WinSetFocus(HWND_DESKTOP, G_hwndProcView);
else
WinSetFocus(HWND_DESKTOP, G_hwndProcListCnr);
}
else
{
if ( (usch == 'p')
&& (usFlags & KC_CTRL)
)
{
CHAR szRet[100];
DosBeep(1000, 100);
sprintf(szRet, "return code: %d",
txvPrintWindow(G_hwndProcView,
"Process dump",
PrintCallback));
winhDebugBox(0, "print", szRet);
}
}
mrc = (MPARAM)TRUE;
break; }
case WM_CLOSE:
winhSaveWindowPos(G_hwndMain,
HINI_USER,
INIAPP,
INIKEY_MAINWINPOS);
mrc = WinDefWindowProc(hwndClient, msg, mp1, mp2);
break;
default:
mrc = WinDefWindowProc(hwndClient, msg, mp1, mp2);
}
return (mrc);
}
/*
*@@ LoadNLS:
* load NLS interface.
*
*/
BOOL LoadNLS(VOID)
{
CHAR szNLSDLL[2*CCHMAXPATH];
BOOL Proceed = TRUE;
if (PrfQueryProfileString(HINI_USER,
"XWorkplace",
"XFolderPath",
"",
szNLSDLL, sizeof(szNLSDLL)) < 3)
{
WinMessageBox(HWND_DESKTOP, HWND_DESKTOP,
"xpstat was unable to determine the location of the "
"XWorkplace National Language Support DLL, which is "
"required for operation. The OS2.INI file does not contain "
"this information. "
"xpstat cannot proceed. Please re-install XWorkplace.",
"xpstat: Fatal Error",
0, MB_OK | MB_MOVEABLE);
Proceed = FALSE;
}
else
{
CHAR szLanguageCode[50] = "";
// now compose module name from language code
PrfQueryProfileString(HINI_USERPROFILE,
"XWorkplace", "Language",
"001",
(PVOID)szLanguageCode,
sizeof(szLanguageCode));
strcat(szNLSDLL, "\\bin\\xfldr");
strcat(szNLSDLL, szLanguageCode);
strcat(szNLSDLL, ".dll");
// try to load the module
if (DosLoadModule(NULL,
0,
szNLSDLL,
&G_hmodNLS))
{
CHAR szMessage[2000];
sprintf(szMessage,
"xpstat was unable to load \"%s\", "
"the National Language DLL which "
"is specified for XWorkplace in OS2.INI.",
szNLSDLL);
WinMessageBox(HWND_DESKTOP, HWND_DESKTOP,
szMessage,
"xpstat: Fatal Error",
0, MB_OK | MB_MOVEABLE);
Proceed = FALSE;
}
}
return (Proceed);
}
/*
* main:
* program entry point.
*/
int main(int argc, char *argv[])
{
QMSG qmsg;
if (!(G_hab = WinInitialize(0)))
return FALSE;
if (!(G_hmq = WinCreateMsgQueue(G_hab, 0)))
return FALSE;
// now attempt to find the XWorkplace NLS resource DLL,
// which we need for all resources (new with XWP 0.9.0)
if (LoadNLS())
{
SWP swpFrame;
swpFrame.x = 100;
swpFrame.y = 100;
swpFrame.cx = 500;
swpFrame.cy = 500;
swpFrame.hwndInsertBehind = HWND_TOP;
swpFrame.fl = SWP_MOVE | SWP_SIZE;
if ( WinRegisterClass(G_hab,
(PSZ)pcszClientClass,
fnwpProcInfoClient,
CS_SIZEREDRAW | CS_SYNCPAINT,
sizeof(PVOID))
&& txvRegisterTextView(G_hab)
)
{
HPOINTER hptrMain = WinLoadPointer(HWND_DESKTOP,
NULLHANDLE,
1);
HWND hwndClient;
G_hwndMain = winhCreateStdWindow(HWND_DESKTOP,
&swpFrame,
FCF_SYSMENU
| FCF_SIZEBORDER
| FCF_TITLEBAR
| FCF_MINMAX
| FCF_NOBYTEALIGN,
WS_CLIPCHILDREN,
"xpstat",
0,
(PSZ)pcszClientClass,
WS_VISIBLE,
0,
NULL,
&hwndClient);
G_hMainMenu = WinLoadMenu(G_hwndMain,
NULLHANDLE,
ID_XPSM_MAIN);
// now position the frame and the client:
// 1) frame
if (!winhRestoreWindowPos(G_hwndMain,
HINI_USER,
INIAPP,
INIKEY_MAINWINPOS,
SWP_MOVE | SWP_SIZE))
// INI data not found:
WinSetWindowPos(G_hwndMain,
HWND_TOP,
100, 100,
500, 500,
SWP_MOVE | SWP_SIZE);
SetupMenu();
// add to task list
winhAddToTasklist(G_hwndMain,
hptrMain);
// finally, show window
WinShowWindow(G_hwndMain, TRUE);
while (WinGetMsg(G_hab, &qmsg, 0, 0, 0))
WinDispatchMsg(G_hab, &qmsg);
}
} // end if (proceed)
// clean up on the way out
WinDestroyMsgQueue(G_hmq);
WinTerminate(G_hab);
return TRUE;
}