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.
1856 lines
42 KiB
1856 lines
42 KiB
#include <windows.h>
|
|
#include <port1632.h>
|
|
#include <ddeml.h>
|
|
#include "wrapper.h"
|
|
#include "ddestrs.h"
|
|
|
|
VOID PaintTest(HWND,PAINTSTRUCT *);
|
|
HWND CreateButton(HWND);
|
|
HANDLE hExtraMem=0;
|
|
LPSTR pszNetName=NULL;
|
|
HANDLE hmemNet=NULL;
|
|
BOOL fnoClose=TRUE;
|
|
|
|
LONG FAR PASCAL MainWndProc(
|
|
HWND hwnd,
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LONG lParam)
|
|
{
|
|
PAINTSTRUCT ps;
|
|
HBRUSH hBrush;
|
|
MSG msg;
|
|
LONG l;
|
|
LONG lflags;
|
|
HWND hbutton;
|
|
|
|
#ifdef WIN32
|
|
HANDLE hmem;
|
|
LPCRITICAL_SECTION lpcs;
|
|
#endif
|
|
|
|
switch (message) {
|
|
case WM_COMMAND:
|
|
|
|
#ifdef WIN32
|
|
if(LOWORD(wParam)==0 && HIWORD(wParam)==BN_CLICKED)
|
|
SendMessage(hwnd,WM_CLOSE,0,0L);
|
|
|
|
if(LOWORD(wParam)==1 && HIWORD(wParam)==BN_CLICKED) {
|
|
|
|
hbutton=GetDlgItem(hwnd,1);
|
|
lflags=GetWindowLong(hwnd,OFFSET_FLAGS);
|
|
|
|
if(lflags&FLAG_PAUSE) {
|
|
SetFlag(hwnd,FLAG_PAUSE,OFF);
|
|
SetWindowText(hbutton,"Pause");
|
|
CheckDlgButton(hwnd,1,0);
|
|
SetFocus(hwnd);
|
|
UpdateWindow(hbutton);
|
|
TimerFunc(hwndMain,WM_TIMER,1,0);
|
|
}
|
|
else {
|
|
SetFlag(hwnd,FLAG_PAUSE,ON);
|
|
SetWindowText(hbutton,"Start");
|
|
CheckDlgButton(hwnd,1,0);
|
|
SetFocus(hwnd);
|
|
InvalidateRect(hbutton,NULL,FALSE);
|
|
UpdateWindow(hbutton);
|
|
}
|
|
}
|
|
|
|
#else
|
|
if(wParam==1 && HIWORD(lParam)==BN_CLICKED) {
|
|
|
|
hbutton=GetDlgItem(hwnd,1);
|
|
lflags=GetWindowLong(hwnd,OFFSET_FLAGS);
|
|
|
|
if(lflags&FLAG_PAUSE) {
|
|
SetFlag(hwnd,FLAG_PAUSE,OFF);
|
|
SetWindowText(GetDlgItem(hwnd,1),"Pause");
|
|
TimerFunc(hwndMain,WM_TIMER,1,0);
|
|
CheckDlgButton(hwnd,1,0);
|
|
SetFocus(hwnd);
|
|
InvalidateRect(hbutton,NULL,FALSE);
|
|
UpdateWindow(hbutton);
|
|
}
|
|
else {
|
|
SetFlag(hwnd,FLAG_PAUSE,ON);
|
|
SetWindowText(GetDlgItem(hwnd,1),"Start");
|
|
CheckDlgButton(hwnd,1,0);
|
|
SetFocus(hwnd);
|
|
InvalidateRect(hbutton,NULL,FALSE);
|
|
UpdateWindow(hbutton);
|
|
}
|
|
}
|
|
|
|
|
|
if(wParam==0 && HIWORD(lParam)==BN_CLICKED)
|
|
SendMessage(hwnd,WM_CLOSE,0,0L);
|
|
#endif
|
|
break;
|
|
|
|
case WM_ENDSESSION:
|
|
case WM_CLOSE:
|
|
|
|
// Shutdown timers
|
|
|
|
if (fClient)
|
|
{
|
|
CloseClient();
|
|
}
|
|
else {
|
|
KillTimer(hwndMain,(UINT)GetThreadLong(GETCURRENTTHREADID(),OFFSET_SERVERTIMER));
|
|
}
|
|
|
|
l=GetWindowLong(hwndMain,OFFSET_FLAGS);
|
|
|
|
#ifdef WIN32
|
|
if(l&FLAG_MULTTHREAD) {
|
|
|
|
// Start conversations disconnecting.
|
|
|
|
ThreadDisconnect();
|
|
|
|
// Start child thread exit
|
|
|
|
ThreadShutdown();
|
|
|
|
}
|
|
#endif
|
|
|
|
// This will stop us using hwndDisplay and hwndMain
|
|
// after there destroyed.
|
|
|
|
SetFlag(hwnd,FLAG_STOP,ON);
|
|
|
|
UninitializeDDE();
|
|
|
|
// Free memory allocated for Net address.
|
|
|
|
if(l&FLAG_NET) {
|
|
if(hmemNet) FreeMem(hmemNet);
|
|
hmemNet=0;
|
|
}
|
|
|
|
// Clean out message queue (main thread)
|
|
|
|
while (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
|
|
if(msg.message!=WM_TIMER) {
|
|
TranslateMessage (&msg);
|
|
DispatchMessage (&msg);
|
|
}
|
|
}
|
|
|
|
#ifdef WIN32
|
|
// Can Not rely on the critical section for our flag update
|
|
// after this point.
|
|
|
|
SetFlag(hwnd,FLAG_SYNCPAINT,OFF);
|
|
|
|
// OK, Shutdown is now under way. We need to wait until
|
|
// all child threads exit before removing our critical section
|
|
// and completing shutdown for main thread.
|
|
|
|
|
|
if(l&FLAG_MULTTHREAD) {
|
|
|
|
ThreadWait(hwndMain);
|
|
|
|
hmem=(HANDLE)GetWindowLong(hwndMain,OFFSET_CRITICALSECT);
|
|
SetWindowLong(hwndMain,OFFSET_CRITICALSECT,0L);
|
|
|
|
if(hmem)
|
|
{
|
|
lpcs=GlobalLock(hmem);
|
|
if(lpcs) DeleteCriticalSection(lpcs);
|
|
GlobalUnlock(hmem);
|
|
GlobalFree(hmem);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
FreeThreadInfo(GETCURRENTTHREADID());
|
|
|
|
|
|
// Say goodbye to main window. Child threads must be finished
|
|
// before making this call.
|
|
|
|
DestroyWindow(hwnd);
|
|
break;
|
|
|
|
|
|
case WM_DESTROY:
|
|
PostQuitMessage(0);
|
|
break;
|
|
|
|
|
|
case WM_ERASEBKGND:
|
|
return 1;
|
|
|
|
|
|
case WM_PAINT:
|
|
BeginPaint(hwnd, &ps);
|
|
hBrush=CreateSolidBrush(WHITE);
|
|
FillRect(ps.hdc,&ps.rcPaint,hBrush);
|
|
DeleteObject(hBrush);
|
|
PaintTest(hwnd,&ps);
|
|
EndPaint(hwnd, &ps);
|
|
break;
|
|
|
|
default:
|
|
return(DefWindowProc(hwnd, message, wParam, lParam));
|
|
}
|
|
return(0L);
|
|
}
|
|
|
|
#ifdef WIN32
|
|
BOOL ThreadShutdown( VOID ) {
|
|
INT i,nCount,nId,nOffset;
|
|
|
|
|
|
nCount=GetWindowLong(hwndMain,OFFSET_THRDCOUNT);
|
|
|
|
nOffset=OFFSET_THRD2ID;
|
|
|
|
for(i=0;i<nCount-1;i++) {
|
|
nId=GetWindowLong(hwndMain,nOffset);
|
|
|
|
if(!PostThreadMessage(nId,EXIT_THREAD,0,0L))
|
|
{
|
|
Sleep(200);
|
|
if(!PostThreadMessage(nId,EXIT_THREAD,0,0L)) {
|
|
DOut(hwndMain,"DdeStrs.Exe -- ERR:PostThreadMessage failed 4 EXIT_THREAD\r\n",NULL,0);
|
|
}
|
|
}
|
|
|
|
nOffset=nOffset+4;
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
BOOL ThreadDisconnect( VOID ) {
|
|
INT i,nCount,nId,nOffset;
|
|
|
|
|
|
nCount=GetWindowLong(hwndMain,OFFSET_THRDCOUNT);
|
|
|
|
nOffset=OFFSET_THRD2ID;
|
|
|
|
for(i=0;i<nCount-1;i++) {
|
|
nId=GetWindowLong(hwndMain,nOffset);
|
|
|
|
if(!PostThreadMessage(nId,START_DISCONNECT,0,0L))
|
|
{
|
|
Sleep(200);
|
|
if(!PostThreadMessage(nId,START_DISCONNECT,0,0L)) {
|
|
DOut(hwndMain,"DdeStrs.Exe -- ERR:PostThreadMessage failed 4 START_DISCONNECT\r\n",NULL,0);
|
|
}
|
|
}
|
|
|
|
nOffset=nOffset+4;
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
VOID PaintTest(
|
|
HWND hwnd,
|
|
PAINTSTRUCT *pps)
|
|
{
|
|
RECT rc,r;
|
|
static CHAR szT[40];
|
|
LONG cClienthConvs,cServerhConvs;
|
|
|
|
GetClientRect(hwnd, &rc);
|
|
OffsetRect(&rc, 0, cyText);
|
|
rc.bottom = rc.top + cyText;
|
|
|
|
|
|
#ifdef WIN16
|
|
|
|
// Test Mode
|
|
|
|
if(IntersectRect(&r,&(pps->rcPaint),&rc)) {
|
|
if(fServer && fClient)
|
|
{
|
|
DrawText(pps->hdc, "Client/Server (w16)", -1, &rc, DT_LEFT);
|
|
}
|
|
else {
|
|
if(fServer)
|
|
{
|
|
DrawText(pps->hdc, "Server (w16)", -1, &rc, DT_LEFT);
|
|
}
|
|
else {
|
|
DrawText(pps->hdc, "Client (w16)", -1, &rc, DT_LEFT);
|
|
}
|
|
}
|
|
}
|
|
|
|
OffsetRect(&rc, 0, 2*cyText); // Skip a line before next item
|
|
|
|
#else
|
|
|
|
// Test Mode
|
|
|
|
if(IntersectRect(&r,&(pps->rcPaint),&rc)) {
|
|
if(fServer && fClient)
|
|
{
|
|
DrawText(pps->hdc, "Client/Server (w32)", -1, &rc, DT_LEFT);
|
|
}
|
|
else {
|
|
if(fServer)
|
|
{
|
|
DrawText(pps->hdc, "Server (w32)", -1, &rc, DT_LEFT);
|
|
}
|
|
else {
|
|
DrawText(pps->hdc, "Client (w32)", -1, &rc, DT_LEFT);
|
|
}
|
|
}
|
|
}
|
|
|
|
OffsetRect(&rc, 0, 2*cyText); // Skip a line before next item
|
|
|
|
#endif
|
|
|
|
|
|
// Stress Percentage
|
|
|
|
if(IntersectRect(&r,&(pps->rcPaint),&rc)) {
|
|
DrawText(pps->hdc,"Stress %", -1, &rc, DT_LEFT);
|
|
|
|
#ifdef WIN32
|
|
wsprintf(szT, "%d", GetWindowLong(hwndMain,OFFSET_STRESS));
|
|
#else
|
|
wsprintf(szT, "%ld", GetWindowLong(hwndMain,OFFSET_STRESS));
|
|
#endif
|
|
CopyRect(&r,&rc);
|
|
r.left=cxText*LONGEST_LINE;
|
|
DrawText(pps->hdc, szT, -1, &r, DT_LEFT);
|
|
|
|
}
|
|
|
|
OffsetRect(&rc, 0, cyText);
|
|
|
|
|
|
// Run Time
|
|
|
|
if(IntersectRect(&r,&(pps->rcPaint),&rc)) {
|
|
DrawText(pps->hdc,"Run Time", -1, &rc, DT_LEFT);
|
|
|
|
#ifdef WIN32
|
|
wsprintf(szT, "%d", GetWindowLong(hwndMain,OFFSET_RUNTIME));
|
|
#else
|
|
wsprintf(szT, "%ld", GetWindowLong(hwndMain,OFFSET_RUNTIME));
|
|
#endif
|
|
|
|
CopyRect(&r,&rc);
|
|
r.left=cxText*LONGEST_LINE;
|
|
DrawText(pps->hdc, szT, -1, &r, DT_LEFT);
|
|
}
|
|
|
|
OffsetRect(&rc, 0, cyText);
|
|
|
|
|
|
// Time Elapsed
|
|
|
|
if(IntersectRect(&r,&(pps->rcPaint),&rc)) {
|
|
DrawText(pps->hdc, "Time Elapsed", -1, &rc, DT_LEFT);
|
|
|
|
#ifdef WIN32
|
|
wsprintf(szT, "%d", GetWindowLong(hwndMain,OFFSET_TIME_ELAPSED));
|
|
#else
|
|
wsprintf(szT, "%ld", GetWindowLong(hwndMain,OFFSET_TIME_ELAPSED));
|
|
#endif
|
|
|
|
CopyRect(&r,&rc);
|
|
r.left=cxText*LONGEST_LINE;
|
|
DrawText(pps->hdc, szT, -1, &r, DT_LEFT);
|
|
|
|
}
|
|
|
|
OffsetRect(&rc, 0, cyText);
|
|
|
|
|
|
// *** Count Client Connections ****
|
|
|
|
if(IntersectRect(&r,&(pps->rcPaint),&rc)) {
|
|
|
|
cClienthConvs=GetCurrentCount(hwnd,OFFSET_CCLIENTCONVS);
|
|
DrawText(pps->hdc,"Client Connect", -1, &rc, DT_LEFT);
|
|
|
|
#ifdef WIN32
|
|
wsprintf(szT, "%d", cClienthConvs);
|
|
#else
|
|
wsprintf(szT, "%ld", cClienthConvs);
|
|
#endif
|
|
CopyRect(&r,&rc);
|
|
r.left=cxText*LONGEST_LINE;
|
|
DrawText(pps->hdc, szT, -1, &r, DT_LEFT);
|
|
|
|
} // if IntersectRect
|
|
|
|
OffsetRect(&rc, 0, cyText);
|
|
|
|
|
|
// *** Server Connections ***
|
|
|
|
if(IntersectRect(&r,&(pps->rcPaint),&rc)) {
|
|
DrawText(pps->hdc,"Server Connect", -1, &rc, DT_LEFT);
|
|
|
|
cServerhConvs=GetCurrentCount(hwnd,OFFSET_CSERVERCONVS);
|
|
|
|
#ifdef WIN32
|
|
wsprintf(szT, "%d", cServerhConvs );
|
|
#else
|
|
wsprintf(szT, "%ld", cServerhConvs );
|
|
#endif
|
|
CopyRect(&r,&rc);
|
|
r.left=cxText*LONGEST_LINE;
|
|
DrawText(pps->hdc, szT, -1, &r, DT_LEFT);
|
|
}
|
|
|
|
OffsetRect(&rc, 0, cyText);
|
|
|
|
|
|
// Client Count (for checking balence between apps)
|
|
|
|
if(IntersectRect(&r,&(pps->rcPaint),&rc)) {
|
|
DrawText(pps->hdc,"Client Count", -1, &rc, DT_LEFT);
|
|
|
|
#ifdef WIN32
|
|
wsprintf(szT, "%d",GetWindowLong(hwnd,OFFSET_CLIENT));
|
|
#else
|
|
wsprintf(szT, "%ld",GetWindowLong(hwnd,OFFSET_CLIENT));
|
|
#endif
|
|
CopyRect(&r,&rc);
|
|
r.left=cxText*LONGEST_LINE;
|
|
DrawText(pps->hdc, szT, -1, &r, DT_LEFT);
|
|
}
|
|
|
|
OffsetRect(&rc, 0, cyText);
|
|
|
|
|
|
// Server Count (for checking balence between apps)
|
|
|
|
if(IntersectRect(&r,&(pps->rcPaint),&rc)) {
|
|
DrawText(pps->hdc,"Server Count", -1, &rc, DT_LEFT);
|
|
|
|
#ifdef WIN32
|
|
wsprintf(szT, "%d", GetWindowLong(hwnd,OFFSET_SERVER));
|
|
#else
|
|
wsprintf(szT, "%ld", GetWindowLong(hwnd,OFFSET_SERVER));
|
|
#endif
|
|
CopyRect(&r,&rc);
|
|
r.left=cxText*LONGEST_LINE;
|
|
DrawText(pps->hdc, szT, -1, &r, DT_LEFT);
|
|
}
|
|
|
|
OffsetRect(&rc, 0, cyText);
|
|
|
|
|
|
// Delay
|
|
|
|
if(IntersectRect(&r,&(pps->rcPaint),&rc)) {
|
|
DrawText(pps->hdc,"Delay", -1, &rc, DT_LEFT);
|
|
|
|
#ifdef WIN32
|
|
wsprintf(szT, "%d", GetWindowLong(hwndMain,OFFSET_DELAY));
|
|
#else
|
|
wsprintf(szT, "%ld", GetWindowLong(hwndMain,OFFSET_DELAY));
|
|
#endif
|
|
CopyRect(&r,&rc);
|
|
r.left=cxText*LONGEST_LINE;
|
|
DrawText(pps->hdc, szT, -1, &r, DT_LEFT);
|
|
}
|
|
|
|
OffsetRect(&rc, 0, cyText);
|
|
|
|
}
|
|
|
|
int PASCAL WinMain(
|
|
HINSTANCE hInstance,
|
|
HINSTANCE hPrev,
|
|
LPSTR lpszCmdLine,
|
|
int cmdShow)
|
|
{
|
|
MSG msg;
|
|
HDC hdc;
|
|
WNDCLASS wc;
|
|
TEXTMETRIC tm;
|
|
INT x,y,cx,cy;
|
|
#ifdef WIN32
|
|
LONG lflags;
|
|
#endif
|
|
DWORD idI;
|
|
HWND hwndDisplay;
|
|
INT nThrd;
|
|
|
|
CHAR sz[250];
|
|
CHAR sz2[250];
|
|
LPSTR lpszOut=&sz[0];
|
|
LPSTR lpsz=&sz2[0];
|
|
|
|
#ifdef WIN32
|
|
DWORD dwer;
|
|
#endif
|
|
|
|
hInst=hInstance;
|
|
|
|
if(!SetMessageQueue(100)) {
|
|
MessageBox(NULL,"SetMessageQueue failed. Test aborting.","Error:DdeStrs",MB_ICONSTOP|MB_OK);
|
|
return FALSE;
|
|
}
|
|
|
|
wc.style = 0;
|
|
wc.lpfnWndProc = MainWndProc;
|
|
wc.cbClsExtra = 0;
|
|
wc.cbWndExtra = WND;
|
|
wc.hInstance = hInst;
|
|
wc.hIcon = LoadIcon(hInst,MAKEINTRESOURCE(IDR_ICON));
|
|
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
wc.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE+1);
|
|
wc.lpszMenuName = NULL;
|
|
wc.lpszClassName = szClass;
|
|
|
|
if(!hPrev) {
|
|
if (!RegisterClass(&wc) )
|
|
{
|
|
#if 0
|
|
// This was removed because the system was running out of resources (ALPHA only)
|
|
// which caused this occasionaly to fail. Rather than continue to bring
|
|
// the message box up (for a known stress situation) the test will abort
|
|
// and try again.
|
|
|
|
MessageBox(NULL,"RegisterClass failed. Test aborting.","Error:DdeStrs",MB_ICONSTOP|MB_OK);
|
|
#endif
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
hwndMain = CreateWindowEx( WS_EX_DLGMODALFRAME,
|
|
szClass,
|
|
szClass,
|
|
WS_OVERLAPPED|WS_MINIMIZEBOX|WS_CLIPCHILDREN,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
hInst,
|
|
NULL);
|
|
|
|
#ifdef WIN32
|
|
dwer=GetLastError(); // We want LastError Associated with CW call
|
|
#endif
|
|
|
|
if (!hwndMain) {
|
|
MessageBox(NULL,"Could Not Create Main Window. Test aborting.","Error:DdeStrs",MB_ICONSTOP|MB_OK);
|
|
UnregisterClass(szClass,hInst);
|
|
return FALSE;
|
|
}
|
|
|
|
#ifdef WIN32
|
|
if (!IsWindow(hwndMain)) {
|
|
TStrCpy(lpsz,"CreateWindowEx failed for Main Window but did not return NULL! Test aborting. HWND=%u, LastEr=%u");
|
|
wsprintf(lpszOut,lpsz,hwndMain,dwer);
|
|
MessageBox(NULL,lpszOut,"Error:DdeStrs",MB_ICONSTOP|MB_OK);
|
|
UnregisterClass(szClass,hInst);
|
|
return FALSE;
|
|
}
|
|
#else
|
|
if (!IsWindow(hwndMain)) {
|
|
TStrCpy(lpsz,"CreateWindowEx failed for Main Window but did not return NULL! Test aborting. HWND=%u");
|
|
wsprintf(lpszOut,lpsz,hwndMain);
|
|
MessageBox(NULL,lpszOut,"Error:DdeStrs",MB_ICONSTOP|MB_OK);
|
|
UnregisterClass(szClass,hInst);
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
|
|
if (!ParseCommandLine(hwndMain,lpszCmdLine)) {
|
|
DestroyWindow(hwndMain);
|
|
UnregisterClass(szClass,hInst);
|
|
return FALSE;
|
|
}
|
|
|
|
// Note: This needs to be there even for win 16 execution. The
|
|
// name may be confusing. for win 16 there is obviously only
|
|
// a single thread. This is handled by the call.
|
|
|
|
|
|
nThrd=GetWindowLong(hwndMain,OFFSET_THRDCOUNT);
|
|
|
|
// Currently ddestrs has a hardcoded thread limit (at THREADLIMIT). So
|
|
// this should NEVER be less than one or greater than THREADLIMIT.
|
|
|
|
#ifdef WIN32
|
|
if(nThrd<1 || nThrd>THREADLIMIT) {
|
|
BOOL fVal;
|
|
|
|
dwer=GetLastError();
|
|
|
|
if(IsWindow(hwndMain)) fVal=TRUE;
|
|
else fVal=FALSE;
|
|
|
|
TStrCpy(lpsz,"GetWindowLong failed querying thread count!. Test aborting... INFO:hwnd=%u, LastEr=%u, Is hwnd valid=%u, nThrd=%u");
|
|
|
|
wsprintf(lpszOut,lpsz,hwndMain,dwer,fVal,nThrd);
|
|
MessageBox(NULL,lpszOut,"Error:DdeStrs",MB_ICONSTOP|MB_OK);
|
|
|
|
DestroyWindow(hwndMain);
|
|
UnregisterClass(szClass,hInst);
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
|
|
if(!CreateThreadExtraMem( EXTRA_THREAD_MEM,nThrd)) {
|
|
MessageBox(NULL,"Could Not Alocate Get/SetThreadLong(). Test aborting.","Error:DdeStrs",MB_ICONSTOP|MB_OK);
|
|
DestroyWindow(hwndMain);
|
|
UnregisterClass(szClass,hInst);
|
|
return FALSE;
|
|
}
|
|
|
|
// We always need the thread id for the main thread. (for use
|
|
// in Get/SetThreadLong(). Other thread id's are initialized in
|
|
// ThreadInit().
|
|
|
|
SetWindowLong(hwndMain,OFFSET_THRDMID,GETCURRENTTHREADID());
|
|
|
|
if(!InitThreadInfo(GETCURRENTTHREADID())) {
|
|
MessageBox(NULL,"Could Not Alocate Thread Local Storage. Test aborting.","Error:DdeStrs",MB_ICONSTOP|MB_OK);
|
|
DestroyWindow(hwndMain);
|
|
UnregisterClass(szClass,hInst);
|
|
return FALSE;
|
|
}
|
|
|
|
hdc = GetDC(hwndMain);
|
|
GetTextMetrics(hdc, &tm);
|
|
|
|
cyText = tm.tmHeight;
|
|
cxText = tm.tmAveCharWidth;
|
|
|
|
// We need to add in extra area for each additional DisplayWindow
|
|
// used for each addtional thread.
|
|
|
|
nThrd=(INT)GetWindowLong(hwndMain,OFFSET_THRDCOUNT);
|
|
cy = tm.tmHeight*NUM_ROWS+((nThrd-1)*(3*cyText));
|
|
cx = tm.tmAveCharWidth*NUM_COLUMNS;
|
|
|
|
ReleaseDC(hwndMain,hdc);
|
|
|
|
// Old ways of positioning.
|
|
|
|
// y=DIV((GetSystemMetrics(SM_CYSCREEN)-cy),3)*2;
|
|
// y=(DIV(GetSystemMetrics(SM_CYSCREEN),10)*3);
|
|
|
|
// Position as if 5 threads with bottom of window at bottom of
|
|
// screen.
|
|
|
|
y=GetSystemMetrics(SM_CYSCREEN)-(tm.tmHeight*NUM_ROWS+(12*cyText));
|
|
|
|
x=GetSystemMetrics(SM_CXSCREEN);
|
|
|
|
if(fServer && fClient) {
|
|
x=x-(cx*3); // Init for standard values.
|
|
}
|
|
else {
|
|
if(fServer)
|
|
{
|
|
x=x-cx;
|
|
}
|
|
else {
|
|
x=x-(cx*2);
|
|
}
|
|
}
|
|
|
|
SetWindowPos( hwndMain,
|
|
NULL,
|
|
x,
|
|
y,
|
|
cx,
|
|
cy,
|
|
SWP_NOZORDER|SWP_NOACTIVATE );
|
|
|
|
ShowWindow (hwndMain, cmdShow);
|
|
|
|
CreateButton(hwndMain);
|
|
|
|
UpdateWindow (hwndMain);
|
|
|
|
#ifdef WIN32
|
|
SetFlag(hwndMain,FLAG_SYNCPAINT,ON);
|
|
|
|
lflags=GetWindowLong(hwndMain,OFFSET_FLAGS);
|
|
if(lflags&FLAG_MULTTHREAD) { // CreateThreads
|
|
if(!ThreadInit(hwndMain)) {
|
|
DestroyWindow(hwndMain);
|
|
UnregisterClass(szClass,hInst);
|
|
return FALSE;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
hwndDisplay=CreateDisplayWindow(hwndMain,1);
|
|
|
|
if(!hwndDisplay) {
|
|
MessageBox(NULL,"Could Not Create Test Display Window. Test aborting.","Error:DdeStrs",MB_ICONSTOP|MB_OK);
|
|
DestroyWindow(hwndMain);
|
|
UnregisterClass(szClass,hInst);
|
|
return FALSE;
|
|
}
|
|
else {
|
|
SetThreadLong(GETCURRENTTHREADID(),OFFSET_HWNDDISPLAY,(LONG)hwndDisplay);
|
|
}
|
|
|
|
if (!InitializeDDE((PFNCALLBACK)CustomCallback,
|
|
&idI,
|
|
ServiceInfoTable,
|
|
fServer ?
|
|
APPCLASS_STANDARD
|
|
:
|
|
APPCLASS_STANDARD | APPCMD_CLIENTONLY,
|
|
hInst)) {
|
|
DDEMLERROR("DdeStrs.Exe -- Error Dde inititialization failed\r\n");
|
|
DestroyWindow(hwndMain);
|
|
UnregisterClass(szClass,hInst);
|
|
return(FALSE);
|
|
}
|
|
|
|
SetThreadLong(GETCURRENTTHREADID(),OFFSET_IDINST,idI);
|
|
|
|
if (fClient)
|
|
{
|
|
InitClient();
|
|
}
|
|
else {
|
|
|
|
// Only needed if we are not a client. In case of
|
|
// client/server only call InitClient() which start
|
|
// a timer which can be used for time checks.
|
|
|
|
SetTimer( hwndMain,
|
|
(UINT)GetThreadLong(GETCURRENTTHREADID(),OFFSET_SERVERTIMER),
|
|
PNT_INTERVAL,
|
|
TimerFunc);
|
|
}
|
|
|
|
while (GetMessage(&msg, NULL, 0, 0)) {
|
|
|
|
if(IsTimeExpired(hwndMain)) {
|
|
|
|
// We only want to send a single WM_CLOSE
|
|
|
|
if(fnoClose) {
|
|
fnoClose=FALSE;
|
|
PostMessage(hwndMain,WM_CLOSE,0,0L);
|
|
}
|
|
}
|
|
|
|
TranslateMessage (&msg);
|
|
DispatchMessage (&msg);
|
|
}
|
|
|
|
FreeThreadExtraMem();
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
#ifdef WIN32
|
|
/************************** Private Function ****************************\
|
|
*
|
|
* ThreadInit
|
|
*
|
|
* Create secondary test threads
|
|
*
|
|
\**************************************************************************/
|
|
|
|
BOOL ThreadInit( HWND hwnd ) {
|
|
LONG l,ll;
|
|
PLONG lpIDThread=≪
|
|
HANDLE hthrd;
|
|
INT nOffset,nCount,i,n;
|
|
HANDLE hmem;
|
|
HANDLE *lph;
|
|
char sz[20];
|
|
LPSTR lpsz=&sz[0];
|
|
|
|
nCount=GetWindowLong(hwnd,OFFSET_THRDCOUNT);
|
|
nOffset=OFFSET_THRD2;
|
|
|
|
for(i=1;i<nCount;i++) {
|
|
|
|
hmem=GetMemHandle(((sizeof(HANDLE)*2)+sizeof(INT)));
|
|
lph=(HANDLE *)GlobalLock(hmem);
|
|
|
|
*lph=hwnd;
|
|
*(lph+1)=hmem;
|
|
*(lph+2)=(HANDLE)(i+1);
|
|
|
|
hthrd=CreateThread(NULL,0,SecondaryThreadMain,(LPVOID)lph,0,lpIDThread);
|
|
|
|
if (!hthrd) {
|
|
|
|
DOut(hwnd,"DdeStrs.Exe -- ERR:Could not Create Thread #%u\r\n",0,i+1);
|
|
|
|
GlobalUnlock(hmem);
|
|
FreeMemHandle(hmem);
|
|
|
|
// it's important we turn this flag off since no threads
|
|
// where successfully created (cleanup code)
|
|
|
|
SetFlag(hwnd,FLAG_MULTTHREAD,OFF);
|
|
|
|
if (i==1) return FALSE;
|
|
else {
|
|
|
|
// Cleanup threads before we abort.
|
|
|
|
for(n=1;n<i;n++) {
|
|
nOffset=OFFSET_THRD2;
|
|
TerminateThread((HANDLE)GetWindowLong(hwnd,nOffset),0);
|
|
SetWindowLong(hwnd,nOffset,0L);
|
|
nOffset=nOffset+4;
|
|
} // for
|
|
|
|
return FALSE;
|
|
|
|
} // else
|
|
|
|
} // if
|
|
|
|
SetWindowLong(hwnd,nOffset+ID_OFFSET,(LONG)(*lpIDThread));
|
|
SetWindowLong(hwnd,nOffset,(LONG)hthrd);
|
|
|
|
nOffset=nOffset+4;
|
|
|
|
} // for
|
|
|
|
|
|
return TRUE;
|
|
|
|
} // ThreadInit
|
|
|
|
/*************************** Private Function ******************************\
|
|
SecondaryThreadMain
|
|
|
|
Effects: Start of execution for second thread. First order of buisness is
|
|
create the test window and start queue processing.
|
|
|
|
Return value:
|
|
|
|
\***************************************************************************/
|
|
|
|
DWORD SecondaryThreadMain( DWORD dw )
|
|
{
|
|
HWND hwndMain;
|
|
MSG msg;
|
|
HANDLE * lph;
|
|
HANDLE hmem;
|
|
INT nThrd;
|
|
DWORD idI;
|
|
HWND hwndDisplay;
|
|
LONG nTc;
|
|
|
|
lph=(HANDLE *)dw;
|
|
|
|
hwndMain=(HWND)*lph;
|
|
hmem =(HANDLE)*(lph+1);
|
|
nThrd =(INT)*(lph+2);
|
|
|
|
GlobalUnlock(hmem);
|
|
FreeMemHandle(hmem);
|
|
|
|
if(!InitThreadInfo(GETCURRENTTHREADID())) {
|
|
DDEMLERROR("DdeStrs.Exe -- Error InitThreadInfo failed, Aborting thread\r\n");
|
|
nTc=GetWindowLong(hwndMain,OFFSET_THRDCOUNT);
|
|
SetWindowLong(hwndMain,OFFSET_THRDCOUNT,(LONG)(nTc-1));
|
|
ExitThread(1L);
|
|
}
|
|
|
|
SetThreadLong(GETCURRENTTHREADID(),OFFSET_IDINST,idI);
|
|
|
|
hwndDisplay=CreateDisplayWindow( hwndMain,
|
|
IDtoTHREADNUM(GETCURRENTTHREADID()));
|
|
|
|
if(!IsWindow(hwndDisplay)) {
|
|
DDEMLERROR("DdeStrs.Exe -- ERR:Could not create Display Window, Thread aborting\r\n");
|
|
nTc=GetWindowLong(hwndMain,OFFSET_THRDCOUNT);
|
|
SetWindowLong(hwndMain,OFFSET_THRDCOUNT,(LONG)(nTc-1));
|
|
ExitThread(1L);
|
|
return FALSE;
|
|
}
|
|
else {
|
|
SetThreadLong(GETCURRENTTHREADID(),OFFSET_HWNDDISPLAY,hwndDisplay);
|
|
}
|
|
|
|
if (!InitializeDDE((PFNCALLBACK)CustomCallback,
|
|
&idI,
|
|
ServiceInfoTable,
|
|
fServer ?
|
|
APPCLASS_STANDARD
|
|
:
|
|
APPCLASS_STANDARD | APPCMD_CLIENTONLY,
|
|
hInst)) {
|
|
DDEMLERROR("DdeStrs.Exe -- Error Dde inititialization failed for secondary thread!\r\n");
|
|
FreeThreadInfo(GETCURRENTTHREADID());
|
|
nTc=GetWindowLong(hwndMain,OFFSET_THRDCOUNT);
|
|
SetWindowLong(hwndMain,OFFSET_THRDCOUNT,(LONG)(nTc-1));
|
|
ExitThread(1L);
|
|
}
|
|
|
|
if (fClient)
|
|
{
|
|
InitClient();
|
|
}
|
|
else {
|
|
|
|
// Only needed if we are not a client. In case of
|
|
// client/server only call InitClient() which start
|
|
// a timer which can be used for time checks.
|
|
|
|
SetTimer( hwndMain,
|
|
(UINT)GetThreadLong(GETCURRENTTHREADID(),OFFSET_SERVERTIMER),
|
|
PNT_INTERVAL,
|
|
TimerFunc);
|
|
}
|
|
|
|
while (GetMessage(&msg,NULL,0,0)) {
|
|
|
|
if(msg.message==START_DISCONNECT)
|
|
{
|
|
if (fClient)
|
|
{
|
|
CloseClient();
|
|
}
|
|
}
|
|
else {
|
|
if(msg.message==EXIT_THREAD)
|
|
{
|
|
PostQuitMessage(1);
|
|
}
|
|
else {
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
} // EXIT_THREAD
|
|
|
|
} // START_DISCONNECT
|
|
|
|
} // while
|
|
|
|
SetFlag(hwndMain,FLAG_STOP,ON);
|
|
|
|
// Shutdown timers
|
|
|
|
if (!fClient)
|
|
{
|
|
KillTimer(hwndMain,GetThreadLong(GETCURRENTTHREADID(),OFFSET_SERVERTIMER));
|
|
}
|
|
|
|
UninitializeDDE();
|
|
|
|
FreeThreadInfo(GETCURRENTTHREADID());
|
|
|
|
|
|
// This is to release the semaphore set before completing
|
|
// exit on main thread.
|
|
|
|
|
|
switch (nThrd) {
|
|
|
|
case 2: SetFlag(hwndMain,FLAG_THRD2,ON);
|
|
break;
|
|
case 3: SetFlag(hwndMain,FLAG_THRD3,ON);
|
|
break;
|
|
case 4: SetFlag(hwndMain,FLAG_THRD4,ON);
|
|
break;
|
|
case 5: SetFlag(hwndMain,FLAG_THRD5,ON);
|
|
break;
|
|
default:
|
|
DOut(hwndMain,"DdeStrs.Exe -- ERR: Unexpected switch value in SecondaryThreadMain, value=%u\r\n",0,nThrd);
|
|
break;
|
|
|
|
} // switch
|
|
|
|
ExitThread(1L);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
/************************** Public Function *****************************\
|
|
*
|
|
* InitThrdInfo - This routine allocates memory needed for storage for
|
|
* thread local variables. This routine needs to be called
|
|
* for each thread.
|
|
*
|
|
* Note: I am relying on the fact that the call GetMemHandle() calls
|
|
* GlobalAlloc() specifying the GMEM_ZEROINIT flag. These value need
|
|
* to be zero starting off.
|
|
\**************************************************************************/
|
|
|
|
BOOL InitThreadInfo( DWORD dwid ) {
|
|
HANDLE hmem;
|
|
INT nThrd;
|
|
|
|
hmem = GetMemHandle(sizeof(HCONV)*MAX_SERVER_HCONVS);
|
|
SetThreadLong(dwid,OFFSET_HSERVERCONVS,(LONG)hmem);
|
|
|
|
if( hmem==NULL ) {
|
|
DOut(hwndMain,"DdeStrs.Exe -- ERR: Could not allocate thread local storage(Server Conversation List)\r\n",0,0);
|
|
return FALSE;
|
|
}
|
|
|
|
hmem = GetMemHandle(sizeof(HANDLE)*NUM_FORMATS);
|
|
SetThreadLong(dwid,OFFSET_HAPPOWNED,(LONG)hmem);
|
|
|
|
if( hmem==NULL ) {
|
|
DOut(hwndMain,"DdeStrs.Exe -- ERR: Could not allocate thread local storage(AppOwned Flag List)\r\n",0,0);
|
|
FreeMemHandle((HANDLE)GetThreadLong(dwid,OFFSET_HSERVERCONVS));
|
|
return FALSE;
|
|
}
|
|
|
|
nThrd=IDtoTHREADNUM(dwid);
|
|
|
|
SetThreadLong(dwid,OFFSET_SERVERTIMER,nThrd*2);
|
|
SetThreadLong(dwid,OFFSET_CLIENTTIMER,(nThrd*2)+1);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
#ifdef WIN32
|
|
|
|
/************************** Private Function ****************************\
|
|
*
|
|
* IDtoTHREADNUM - Find out current thread.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
INT IDtoTHREADNUM( DWORD dwid ) {
|
|
INT nWndOff,nThrd,nThrdCount,n;
|
|
|
|
nWndOff=OFFSET_THRDMID;
|
|
nThrdCount=GetWindowLong(hwndMain,OFFSET_THRDCOUNT);
|
|
n=nThrdCount;
|
|
nThrd=1;
|
|
|
|
while( n>0 ) {
|
|
|
|
if(dwid==(DWORD)GetWindowLong(hwndMain,nWndOff))
|
|
{
|
|
n=-1; // Exit loop
|
|
} // if
|
|
else {
|
|
nWndOff=nWndOff+4;
|
|
nThrd++;
|
|
n--;
|
|
}
|
|
} // while
|
|
|
|
if(nThrd>nThrdCount) {
|
|
DDEMLERROR("DdeStrs.Exe -- ERR:Thread Count exceeded!!! in IDtoTHREADNUM()\r\n");
|
|
nThrd=nThrdCount;
|
|
}
|
|
|
|
return nThrd;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
/************************** Private Function ****************************\
|
|
*
|
|
* IDtoTHREADNUM - Find out current thread.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
INT IDtoTHREADNUM( DWORD dwid ) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
/************************** Public Function *****************************\
|
|
*
|
|
* FreeThreadInfo - Free thread information memory.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
BOOL FreeThreadInfo( DWORD dwid ) {
|
|
HANDLE hmem;
|
|
|
|
hmem=(HANDLE)GetThreadLong(dwid,OFFSET_HSERVERCONVS);
|
|
FreeMemHandle(hmem);
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
#ifdef WIN32
|
|
|
|
/************************** Public Function *****************************\
|
|
*
|
|
* ThreadWait - This routine waits while processing messages until the
|
|
* other threads signal they've completed work that must
|
|
* be finished before preceeding.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID ThreadWait( HWND hwnd ) {
|
|
LONG lflags;
|
|
INT nCount,nWait;
|
|
MSG msg;
|
|
|
|
lflags=GetWindowLong(hwnd,OFFSET_FLAGS);
|
|
nCount=GetWindowLong(hwnd,OFFSET_THRDCOUNT);
|
|
|
|
nWait=nCount-1;
|
|
|
|
if(lflags&FLAG_THRD2) nWait-=1;
|
|
if(lflags&FLAG_THRD3) nWait-=1;
|
|
if(lflags&FLAG_THRD4) nWait-=1;
|
|
if(lflags&FLAG_THRD5) nWait-=1;
|
|
|
|
while (nWait>0) {
|
|
|
|
while(PeekMessage(&msg,NULL,0,WM_USER-1,PM_REMOVE)) {
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
} // while peekmessage
|
|
|
|
nWait=nCount-1;
|
|
lflags=GetWindowLong(hwnd,OFFSET_FLAGS);
|
|
|
|
if(lflags&FLAG_THRD2) nWait-=1;
|
|
if(lflags&FLAG_THRD3) nWait-=1;
|
|
if(lflags&FLAG_THRD4) nWait-=1;
|
|
if(lflags&FLAG_THRD5) nWait-=1;
|
|
|
|
} // while nWait
|
|
|
|
// Reset for next wait
|
|
|
|
SetFlag(hwnd,(FLAG_THRD5|FLAG_THRD4|FLAG_THRD3|FLAG_THRD2),OFF);
|
|
|
|
}
|
|
|
|
#endif // WIN32
|
|
|
|
/************************** Private Function ****************************\
|
|
*
|
|
* SetCount
|
|
*
|
|
* This routine updates the count under semaphore protection. Not needed for
|
|
* one thread, but a must for multithread execution.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
LONG SetCount( HWND hwnd, INT nOffset, LONG l, INT ntype ) {
|
|
LONG ll;
|
|
|
|
#if 0
|
|
LONG lflags;
|
|
#endif
|
|
|
|
#ifdef WIN32
|
|
LPCRITICAL_SECTION lpcs;
|
|
HANDLE hmem;
|
|
BOOL f=FALSE;
|
|
#endif
|
|
|
|
#if 0
|
|
|
|
lflags=GetWindowLong(hwnd,OFFSET_FLAGS);
|
|
if(ll&FLAG_MULTTHREAD) {
|
|
f=TRUE;
|
|
hmem=(HANDLE)GetWindowLong(hwnd,OFFSET_CRITICALSECT);
|
|
|
|
// If we have a valid handle then enter critical section. If
|
|
// the handle is still null proceed without a critical section.
|
|
// The first calls to this routine are used to setup the
|
|
// critical section so we do expect those first calls (while
|
|
// we are still sencronized ) for the hmem to be null.
|
|
|
|
if(hmem) {
|
|
lpcs=GlobalLock(hmem);
|
|
EnterCriticalSection(lpcs);
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
// This second GetWindowLong call is needed in the critical
|
|
// section. The test relies very hevily on the flags and
|
|
// it's important to be accurate.
|
|
|
|
ll=GetWindowLong(hwnd,nOffset);
|
|
|
|
if(ntype==INC) l=SetWindowLong(hwnd,nOffset,ll+l);
|
|
else l=SetWindowLong(hwnd,nOffset,ll-l);
|
|
|
|
#if 0
|
|
|
|
if(f) {
|
|
if(hmem) {
|
|
LeaveCriticalSection(lpcs);
|
|
GlobalUnlock(hmem);
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
return l;
|
|
}
|
|
|
|
/************************** Private Function ****************************\
|
|
*
|
|
* SetFlag
|
|
*
|
|
* This routine sets a flag under semaphore protection. Not needed for
|
|
* one thread, but a must for multithread execution.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
LONG SetFlag( HWND hwnd, LONG l, INT ntype ) {
|
|
LONG lflags;
|
|
|
|
#ifdef WIN32
|
|
BOOL fCriticalSect=TRUE;
|
|
LPCRITICAL_SECTION lpcs;
|
|
HANDLE hmem;
|
|
BOOL f=FALSE;
|
|
#endif
|
|
|
|
#ifdef WIN32
|
|
|
|
lflags=GetWindowLong(hwnd,OFFSET_FLAGS);
|
|
if(lflags&FLAG_MULTTHREAD &&
|
|
lflags&FLAG_SYNCPAINT) {
|
|
f=TRUE;
|
|
hmem=(HANDLE)GetWindowLong(hwnd,OFFSET_CRITICALSECT);
|
|
if(hmem) {
|
|
lpcs=GlobalLock(hmem);
|
|
EnterCriticalSection(lpcs);
|
|
}
|
|
else {
|
|
fCriticalSect=FALSE;
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
// This second GetWindowLong call is needed in the critical
|
|
// section. The test relies very hevily on the flags and
|
|
// it's important to be accurate.
|
|
|
|
lflags=GetWindowLong(hwnd,OFFSET_FLAGS);
|
|
|
|
if(ntype==ON) l=SetWindowLong(hwnd,OFFSET_FLAGS,FLAGON(lflags,l));
|
|
else l=SetWindowLong(hwnd,OFFSET_FLAGS,FLAGOFF(lflags,l));
|
|
|
|
#ifdef WIN32
|
|
|
|
if(f) {
|
|
if(fCriticalSect) {
|
|
LeaveCriticalSection(lpcs);
|
|
GlobalUnlock(hmem);
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
return l;
|
|
}
|
|
|
|
/******************************************************************\
|
|
* DIV
|
|
* 05/06/91
|
|
*
|
|
* Performs integer division (format x/y) where DIV(x,y)
|
|
* Works for negative numbers and y==0;
|
|
*
|
|
\******************************************************************/
|
|
|
|
INT DIV( INT x, INT y)
|
|
{
|
|
INT i=0;
|
|
BOOL fNgOn=FALSE;
|
|
|
|
if (!y) return 0; // if div by 0 retrun error.
|
|
|
|
if (x<0 && y>0) fNgOn=TRUE; // keep tabs for negitive numbers
|
|
if (x>0 && y<0) fNgOn=TRUE;
|
|
|
|
if (x<0) x=x*-1;
|
|
if (y<0) y=y*-1;
|
|
|
|
x=x-y;
|
|
|
|
while (x>=0) { // count
|
|
x=x-y;
|
|
i++;
|
|
}
|
|
|
|
if (fNgOn) i=i*(-1); // should result be negative
|
|
|
|
return( i );
|
|
}
|
|
|
|
/*************************** Private Function ******************************\
|
|
*
|
|
* CreateButton
|
|
*
|
|
\***************************************************************************/
|
|
|
|
HWND CreateButton( HWND hwnd ) {
|
|
RECT r;
|
|
HWND hwndB;
|
|
HWND hwndP;
|
|
INT iButWidth;
|
|
LONG lflags;
|
|
|
|
GetClientRect(hwnd,&r);
|
|
|
|
lflags=GetWindowLong(hwnd,OFFSET_FLAGS);
|
|
if(lflags&FLAG_PAUSE_BUTTON) {
|
|
|
|
iButWidth=DIV(r.right-r.left,2);
|
|
|
|
hwndP=CreateWindow("button",
|
|
"Start",
|
|
BS_PUSHBUTTON|WS_VISIBLE|WS_CHILD|WS_CLIPSIBLINGS,
|
|
iButWidth,
|
|
0,
|
|
r.right-iButWidth,
|
|
cyText,
|
|
hwnd,
|
|
1,
|
|
GetHINSTANCE(hwnd),
|
|
0L);
|
|
|
|
if (!hwndP) {
|
|
DDEMLERROR("DdeStrs.Exe -- ERR:Failed to create exit button: Continuing...\r\n");
|
|
SetFlag(hwnd,FLAG_PAUSE_BUTTON,OFF);
|
|
iButWidth=r.right-r.left;
|
|
}
|
|
|
|
|
|
hwndB=CreateWindow("button",
|
|
"Exit",
|
|
BS_PUSHBUTTON|WS_VISIBLE|WS_CHILD|WS_CLIPSIBLINGS,
|
|
0,
|
|
0,
|
|
iButWidth,
|
|
cyText,
|
|
hwnd,
|
|
0,
|
|
GetHINSTANCE(hwnd),
|
|
0L);
|
|
|
|
}
|
|
else {
|
|
|
|
hwndB=CreateWindow("button",
|
|
"Exit",
|
|
BS_PUSHBUTTON|WS_VISIBLE|WS_CHILD|WS_CLIPSIBLINGS,
|
|
0,
|
|
0,
|
|
r.right-r.left,
|
|
cyText,
|
|
hwnd,
|
|
0,
|
|
GetHINSTANCE(hwnd),
|
|
0L);
|
|
}
|
|
|
|
if (!hwndB) {
|
|
DDEMLERROR("DdeStrs.Exe -- ERR:Failed to create exit button: Continuing...\r\n");
|
|
}
|
|
|
|
return hwndB;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* UpdClient
|
|
*
|
|
* The purpose of this routine update only the area invalidated
|
|
* by the test statistics update. If an error occurs in the area
|
|
* calcualation then update the whole client areaa.
|
|
*
|
|
\***************************************************************************/
|
|
|
|
BOOL UpdClient( HWND hwnd, INT iOffset ) {
|
|
RECT r;
|
|
INT iCH,iCW,nThrd;
|
|
|
|
#ifdef WIN32
|
|
DWORD dw;
|
|
#endif
|
|
|
|
// This call aquires the r.right value.
|
|
|
|
GetClientRect(hwnd,&r);
|
|
|
|
// We need text information for the monitor being used. This
|
|
// was initialized in CreateFrame.
|
|
iCH=cyText;
|
|
iCW=cxText;
|
|
|
|
// Do a quick check, if either of these values are NULL then
|
|
// update the whole client area. This is slower and less
|
|
// elegant but will work in the case of an error.
|
|
|
|
if((!iCH) || (!iCW))
|
|
InvalidateRect(hwnd,NULL,TRUE);
|
|
else {
|
|
|
|
// Next Calculate r.top and r.bottom
|
|
|
|
switch(iOffset) {
|
|
|
|
case ALL: // Update all values.
|
|
break;
|
|
|
|
case OFFSET_STRESS:
|
|
r.bottom =iCH*4;
|
|
r.top =iCH*3;
|
|
break;
|
|
|
|
case OFFSET_RUNTIME:
|
|
r.bottom =iCH*5;
|
|
r.top =iCH*4;
|
|
break;
|
|
|
|
case OFFSET_TIME_ELAPSED:
|
|
r.bottom =iCH*6;
|
|
r.top =iCH*5;
|
|
break;
|
|
|
|
case OFFSET_CLIENT_CONNECT:
|
|
r.bottom =iCH*7;
|
|
r.top =iCH*6;
|
|
break;
|
|
|
|
case OFFSET_SERVER_CONNECT:
|
|
r.bottom =iCH*8;
|
|
r.top =iCH*7;
|
|
break;
|
|
|
|
case OFFSET_CLIENT:
|
|
nThrd=(INT)GetWindowLong(hwnd,OFFSET_THRDCOUNT);
|
|
if((GetWindowLong(hwnd,OFFSET_CLIENT)%(NUM_FORMATS*nThrd))==0)
|
|
{
|
|
r.bottom =iCH*9;
|
|
r.top =iCH*8;
|
|
}
|
|
else return TRUE;
|
|
break;
|
|
|
|
case OFFSET_SERVER:
|
|
nThrd=(INT)GetWindowLong(hwnd,OFFSET_THRDCOUNT);
|
|
if((GetWindowLong(hwnd,OFFSET_SERVER)%(NUM_FORMATS*nThrd))==0)
|
|
{
|
|
r.bottom =iCH*10;
|
|
r.top =iCH*9;
|
|
}
|
|
else return TRUE;
|
|
break;
|
|
|
|
case OFFSET_DELAY:
|
|
r.bottom =iCH*11;
|
|
r.top =iCH*10;
|
|
break;
|
|
default:
|
|
break;
|
|
|
|
} // switch
|
|
|
|
// Last we set the r.left and the update rect is complete
|
|
|
|
if(iOffset!=OFFSET_FLAGS)
|
|
r.left = iCW*LONGEST_LINE;
|
|
|
|
InvalidateRect(hwnd,&r,TRUE);
|
|
|
|
} // else
|
|
|
|
#ifdef WIN16
|
|
UpdateWindow(hwnd);
|
|
#else
|
|
SendMessageTimeout(hwnd,WM_PAINT,0,0L,SMTO_NORMAL,500,&dw);
|
|
#endif
|
|
|
|
return TRUE;
|
|
|
|
} // UpdClient
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* GetCurrentCount
|
|
*
|
|
\***************************************************************************/
|
|
|
|
LONG GetCurrentCount( HWND hwnd, INT nOffset ) {
|
|
LONG cClienthConvs =0L;
|
|
INT nThrd,i;
|
|
DWORD dwid;
|
|
|
|
nThrd=(INT)GetWindowLong(hwnd,OFFSET_THRDCOUNT);
|
|
for(i=0;i<nThrd;i++) {
|
|
dwid=(DWORD)GetWindowLong(hwnd,OFFSET_THRDMID+(i*4));
|
|
if(nOffset==OFFSET_CCLIENTCONVS)
|
|
cClienthConvs=cClienthConvs+(INT)GetThreadLong(dwid,OFFSET_CCLIENTCONVS);
|
|
else cClienthConvs=cClienthConvs+(INT)GetThreadLong(dwid,OFFSET_CSERVERCONVS);
|
|
} // for i
|
|
|
|
return cClienthConvs;
|
|
|
|
}
|
|
|
|
/***************************************************************************\
|
|
*
|
|
* UpdateCount
|
|
*
|
|
\***************************************************************************/
|
|
|
|
BOOL UpdateCount( HWND hwnd, INT iOffset, INT i) {
|
|
LONG ll;
|
|
|
|
if(iOffset!=ALL) {
|
|
ll=GetWindowLong(hwnd,iOffset);
|
|
|
|
switch(i) {
|
|
|
|
case INC: SetCount(hwnd,iOffset,1,INC);
|
|
break;
|
|
|
|
case DEC: SetCount(hwnd,iOffset,1,DEC);
|
|
break;
|
|
|
|
case STP: SetFlag(hwnd,FLAG_STOP,ON);
|
|
break;
|
|
|
|
case PNT: // Paint only!
|
|
break;
|
|
|
|
default:
|
|
DDEMLERROR("DdeStrs.Exe - UpdateCount - Unexpected value");
|
|
break;
|
|
|
|
} // switch
|
|
|
|
} // if
|
|
|
|
UpdClient(hwnd,iOffset);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
/*****************************************************************************\
|
|
| DOUT
|
|
|
|
|
| created: 29-Jul-91
|
|
| history: 03-Aug-91 <johnsp> created.
|
|
|
|
|
\*****************************************************************************/
|
|
|
|
BOOL DOut( HWND hwnd, LPSTR lpsz, LPSTR lpszi, INT i ) {
|
|
char sz[MAX_TITLE_LENGTH];
|
|
LPSTR lpszOut=&sz[0];
|
|
LONG lflags;
|
|
|
|
#ifdef WIN32
|
|
LPCRITICAL_SECTION lpcs;
|
|
HANDLE hmem;
|
|
DWORD dwer=0L;
|
|
BOOL fCriticalSect=TRUE;
|
|
BOOL f=FALSE;
|
|
|
|
if(!hwnd) hwnd=hwndMain;
|
|
lflags=GetWindowLong(hwnd,OFFSET_FLAGS);
|
|
|
|
// FLAG_SYNCPAINT implies FLAG_MULTTHREAD with the addition that
|
|
// we have allocated needed resources to start using the
|
|
// critical section code.
|
|
|
|
if(lflags&FLAG_SYNCPAINT) {
|
|
f=TRUE;
|
|
hmem=(HANDLE)GetWindowLong(hwnd,OFFSET_CRITICALSECT);
|
|
if(hmem) {
|
|
lpcs=GlobalLock(hmem);
|
|
EnterCriticalSection(lpcs);
|
|
}
|
|
else {
|
|
fCriticalSect=FALSE;
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
if (lflags&FLAG_DEBUG) {
|
|
|
|
if (lpszi) wsprintf(lpszOut,lpsz,lpszi);
|
|
else wsprintf(lpszOut,lpsz,i);
|
|
|
|
OutputDebugString(lpszOut);
|
|
|
|
#ifdef WIN32
|
|
|
|
dwer=GetLastError();
|
|
wsprintf(lpszOut,"DdeStrs.Exe -- ERR:Val from GetLastError()=%u\n\r",dwer);
|
|
OutputDebugString(lpszOut);
|
|
|
|
#endif
|
|
} // if FLAG_DEBUG
|
|
|
|
#ifdef WIN32
|
|
|
|
// FLAG_SYNCPAINT implies FLAG_MULTTHREAD with the addition that
|
|
// we have allocated needed resources to start using the
|
|
// critical section code.
|
|
|
|
if(f) {
|
|
if(fCriticalSect) {
|
|
LeaveCriticalSection(lpcs);
|
|
GlobalUnlock(hmem);
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
/*****************************************************************************\
|
|
| EOUT
|
|
|
|
|
| created: 19-Aug-92
|
|
| history: 19-Aug-92 <johnsp> created.
|
|
|
|
|
\*****************************************************************************/
|
|
|
|
BOOL EOut( LPSTR lpsz ) {
|
|
|
|
DOut((HWND)NULL,lpsz,(LPSTR)NULL,0);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*************************** Private Function ******************************\
|
|
|
|
GetMemHandle
|
|
|
|
\***************************************************************************/
|
|
|
|
HANDLE GetMemHandle( INT ic ) {
|
|
HANDLE hmem;
|
|
|
|
hmem=GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,ic);
|
|
|
|
if(hmem) {
|
|
SetCount(hwndMain,OFFSET_MEM_ALLOCATED,GlobalSize(hmem),INC);
|
|
}
|
|
else {
|
|
DOut(hwndMain,"DdeStrs.Exe -- ERR:GlobalAlloc ret=%u\n\r",0,0);
|
|
}
|
|
|
|
return hmem;
|
|
|
|
}
|
|
|
|
/*************************** Private Function ******************************\
|
|
|
|
GetMem
|
|
|
|
\***************************************************************************/
|
|
|
|
LPSTR GetMem( INT ic, LPHANDLE lphmem) {
|
|
LPSTR lpsz;
|
|
|
|
*lphmem=GetMemHandle(ic);
|
|
lpsz=GlobalLock(*lphmem);
|
|
|
|
if(!lpsz) {
|
|
DOut(hwndMain,"DdeStrs.Exe -- ERR:GlobalLock ret=%u (not locked)\n\r",0,0);
|
|
FreeMemHandle(*lphmem);
|
|
return NULL;
|
|
}
|
|
|
|
return lpsz;
|
|
|
|
}
|
|
|
|
/*************************** Private Function ******************************\
|
|
|
|
FreeMem
|
|
|
|
\***************************************************************************/
|
|
|
|
BOOL FreeMem( HANDLE hmem ) {
|
|
|
|
if(GlobalUnlock(hmem)) {
|
|
DOut(hwndMain,"DdeStrs.Exe -- ERR:GlobalUnlock ret=%u (still locked)\n\r",0,(INT)TRUE);
|
|
}
|
|
|
|
FreeMemHandle(hmem);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
/*************************** Private Function ******************************\
|
|
|
|
FreeMemHandle
|
|
|
|
\***************************************************************************/
|
|
|
|
BOOL FreeMemHandle( HANDLE hmem ) {
|
|
LONG ll;
|
|
|
|
ll=GlobalSize(hmem);
|
|
|
|
if(!GlobalFree(hmem)) {
|
|
SetCount(hwndMain,OFFSET_MEM_ALLOCATED,ll,DEC);
|
|
}
|
|
else {
|
|
DOut(hwndMain,"DdeStrs.Exe -- ERR:GlobalFree returned %u (not free'd)\n\r",0,(INT)hmem);
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
/**************************** Private *******************************\
|
|
* CreateThreadExtraMem - This routine creates extra thread memory
|
|
* to be used in conjuction with the functions
|
|
* Get/SetThreadLong.
|
|
*
|
|
\********************************************************************/
|
|
|
|
BOOL CreateThreadExtraMem( INT nExtra, INT nThrds ) {
|
|
|
|
hExtraMem=GetMemHandle(nExtra*nThrds);
|
|
SetWindowLong(hwndMain,OFFSET_EXTRAMEM,nExtra);
|
|
|
|
if(hExtraMem==NULL) return FALSE;
|
|
else return TRUE;
|
|
|
|
}
|
|
|
|
/**************************** Private *******************************\
|
|
* FreeThreadExtraMem - This routine frees extra thread memory
|
|
* to be used in conjuction with the functions
|
|
* Get/SetThreadLong.
|
|
*
|
|
* Note: FreeMemHandle can not be used here because it relies on
|
|
* the main window still being around. At this point our
|
|
* main window has already been destroied.
|
|
*
|
|
\********************************************************************/
|
|
|
|
BOOL FreeThreadExtraMem( void ) {
|
|
|
|
GlobalFree(hExtraMem);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
/**************************** Private *******************************\
|
|
* GetThreadLong - This routine queries the value specified by the
|
|
* nOffset parameter from the threads memory areas
|
|
* specified by the dwid value.
|
|
*
|
|
* Memory layout - thread 1: OFFSET1, OFFSET2, ..., OFFSETN
|
|
* thread 2: OFFSET1, OFFSET2, ..., OFFSETN
|
|
* .
|
|
* .
|
|
* thread n: OFFSET1, OFFSET2, ..., OFFSETN
|
|
*
|
|
\********************************************************************/
|
|
|
|
LONG GetThreadLong( DWORD dwid, INT nOffset ) {
|
|
INT nThrd;
|
|
LONG l,lExMem;
|
|
LPBYTE lp;
|
|
LONG FAR *lpl;
|
|
|
|
lp=GlobalLock(hExtraMem);
|
|
|
|
// Find out which thread is making the call.
|
|
|
|
nThrd=IDtoTHREADNUM(dwid);
|
|
|
|
// This is the amount of extra memory for one thread.
|
|
|
|
lExMem=GetWindowLong(hwndMain,OFFSET_EXTRAMEM);
|
|
|
|
// Value at thread and offset. See above for storage layout.
|
|
|
|
lpl=(LONG FAR *)(lp+((nThrd-1)*lExMem)+nOffset);
|
|
|
|
l=*lpl;
|
|
|
|
GlobalUnlock(hExtraMem);
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
/**************************** Private *******************************\
|
|
* SetThreadLong - This routine sets the value specified by the
|
|
* nOffset parameter from the threads memory areas
|
|
* specified by the dwid value.
|
|
*
|
|
* Memory layout - thread 1: OFFSET1, OFFSET2, ..., OFFSETN
|
|
* thread 2: OFFSET1, OFFSET2, ..., OFFSETN
|
|
* .
|
|
* .
|
|
* thread n: OFFSET1, OFFSET2, ..., OFFSETN
|
|
*
|
|
\********************************************************************/
|
|
|
|
LONG SetThreadLong( DWORD dwid, INT nOffset, LONG l ) {
|
|
INT nThrd;
|
|
LONG lPrevValue,lExMem;
|
|
LPBYTE lp;
|
|
LPLONG lpl;
|
|
|
|
lp=GlobalLock(hExtraMem);
|
|
|
|
// Find out which thread is making the call.
|
|
|
|
nThrd=IDtoTHREADNUM(dwid);
|
|
|
|
// This is the amount of extra memory for one thread.
|
|
|
|
lExMem=GetWindowLong(hwndMain,OFFSET_EXTRAMEM);
|
|
|
|
// Value at thread and offset. See above for storage layout.
|
|
|
|
lPrevValue=(LONG)(*(lp+((nThrd-1)*lExMem)+nOffset));
|
|
lpl=(LPLONG)(lp+((nThrd-1)*lExMem)+nOffset);
|
|
|
|
*lpl=l;
|
|
|
|
GlobalUnlock(hExtraMem);
|
|
|
|
return lPrevValue;
|
|
|
|
}
|
|
|
|
|