diff options
Diffstat (limited to 'private/mvdm/wow16/ddeml/tests/ddestrs')
20 files changed, 5909 insertions, 0 deletions
diff --git a/private/mvdm/wow16/ddeml/tests/ddestrs/client.c b/private/mvdm/wow16/ddeml/tests/ddestrs/client.c new file mode 100644 index 000000000..726f50831 --- /dev/null +++ b/private/mvdm/wow16/ddeml/tests/ddestrs/client.c @@ -0,0 +1,160 @@ + +#include <windows.h> +#include <port1632.h> +#include <ddeml.h> +#include <string.h> +#include "wrapper.h" +#include "ddestrs.h" + +extern INT iAvailFormats[]; +extern BOOL UpdateCount(HWND,INT,INT); +extern HANDLE hmemNet; + +void CALLBACK TimerFunc( HWND hwnd, UINT msg, UINT id, DWORD dwTime) +{ + HCONV hConv; + HCONVLIST hConvList; + LONG lflags; + + switch (id%2) { + case 1: + hConv = 0; + hConvList=(HCONVLIST)GetThreadLong(GETCURRENTTHREADID(),OFFSET_HCONVLIST); + while (hConv = DdeQueryNextServer(hConvList, hConv)) { + +// POKE CHANGES +#if 0 + idI=GetThreadLong(GETCURRENTTHREADID(),OFFSET_IDINST); + + if(DdeClientTransaction("Poke Transaction", + strlen("Poke Transaction")+1, + hConv, + DdeCreateStringHandle(idI,"TestItem",CP_WINANSI), + CF_TEXT, + XTYP_POKE, + TIMEOUT_ASYNC, + NULL)==0){ + DDEMLERROR("DdeStrs.Exe -- DdeClientTransaction failed:XTYP_POKE\r\n"); + } +#endif + +// END OF POKE CHANGES + + // Allow 'Pause' functionality -p on command line. + + lflags=GetWindowLong(hwndMain,OFFSET_FLAGS); + if((lflags&FLAG_PAUSE)!=FLAG_PAUSE) + { + + if(DdeClientTransaction(szExecRefresh, + strlen(szExecRefresh) + 1, + hConv, + 0, + 0, + XTYP_EXECUTE, + TIMEOUT_ASYNC, + NULL)==0){ + DDEMLERROR("DdeStrs.Exe -- DdeClientTransaction failed:XTYP_EXECUTE\r\n"); + } + } + } + } + return; +} + +BOOL InitClient() +{ +UINT uid; + + ReconnectList(); + + uid = SetTimer( hwndMain, + (UINT)GetThreadLong(GETCURRENTTHREADID(),OFFSET_CLIENTTIMER), + (UINT)(GetWindowLong(hwndMain,OFFSET_DELAY)), + TimerFunc); + + // This starts the test immidiatly. No delay waiting for the first + // WM_TIMER call. + + TimerFunc(hwndMain,WM_TIMER,uid,0); + + return(TRUE); +} + +VOID CloseClient() +{ +HCONVLIST hConvList; + + hConvList=(HCONVLIST)GetThreadLong(GETCURRENTTHREADID(),OFFSET_HCONVLIST); + KillTimer(hwndMain,(UINT)GetThreadLong(GETCURRENTTHREADID(),OFFSET_CLIENTTIMER)); + if (!DdeDisconnectList(hConvList)) { + DDEMLERROR("DdeStrs.Exe -- DdeDisconnectList failed\r\n"); + } + +} + +VOID ReconnectList() +{ + HCONV hConv; + HCONVLIST hConvList=0; + LONG cClienthConvs; + INT i; + DWORD dwid; + + dwid=GetThreadLong(GETCURRENTTHREADID(),OFFSET_IDINST); + if(dwid==0) { + DDEMLERROR("DdeStrs.Exe -- Null IdInst, aborting Connect!\r\n"); + return; + } + + hConvList = DdeConnectList(dwid, + ServiceInfoTable[0].hszService, + Topics[0].hszTopic, + GetThreadLong(GETCURRENTTHREADID(),OFFSET_HCONVLIST), + NULL); + if (hConvList == 0) { + + // This call is expected to fail in the case of a client + // starting when there is no available server. Just return + // from the routine and continue. + + return; + } + + SetThreadLong(GETCURRENTTHREADID(),OFFSET_HCONVLIST,hConvList); + + hConv = 0; + cClienthConvs = 0L; + + while (hConv = DdeQueryNextServer(hConvList, hConv)) { + for (i=0; i<(int)Items[0].cFormats; i++) { + if (iAvailFormats[i]) { + if (!DdeClientTransaction( NULL, + 0, + hConv, + Items[0].hszItem, + TestItemFormats[i].wFmt, + XTYP_ADVSTART|XTYPF_ACKREQ, + TIMEOUT_ASYNC, + NULL)){ + DDEMLERROR("DdeStrs.Exe -- Error DdeClientTransaction failed\r\n"); + return; + } // if + + } // if + + } // for + + cClienthConvs++; + + } // while + + // Update the client count for the current thread. + + dwid=GETCURRENTTHREADID(); + + SetThreadLong(dwid,OFFSET_CCLIENTCONVS,cClienthConvs); + + UpdateCount(hwndMain,OFFSET_CLIENT_CONNECT,PNT); +} + diff --git a/private/mvdm/wow16/ddeml/tests/ddestrs/cmdln.c b/private/mvdm/wow16/ddeml/tests/ddestrs/cmdln.c new file mode 100644 index 000000000..84504b1bb --- /dev/null +++ b/private/mvdm/wow16/ddeml/tests/ddestrs/cmdln.c @@ -0,0 +1,990 @@ +#include <windows.h> +#include <port1632.h> +#include <ddeml.h> +#include "wrapper.h" +#include "ddestrs.h" + +#ifdef WIN16 +#include <time.h> +#endif + +extern BOOL fServer; +extern BOOL fClient; +extern INT iAvailFormats[]; +extern BOOL UpdateCount(HWND,INT,INT); +extern LPSTR pszNetName; +extern HANDLE hmemNet; +BOOL IsTopicNameFromNetDde(LPSTR,LPSTR); +BOOL FixForNetDdeStartup(HWND,LPSTR); +BOOL FixForStressPercentage(HWND,LPSTR); +BOOL SetStress(HWND,LONG); + + +/***************************************************************************\ +* +* InitArgsError +* +\***************************************************************************/ + +VOID InitArgsError(HWND hwnd, unsigned at) +{ + /* This function informs the user of an error. */ + + static char *mpatszError[] = { + "DdeStrs.Exe -- Invalid command line\r\nTry DdeStrs -5% for standard run or DdeStrs -? for help", + "DdeStrs.Exe -- Invalid number, possibly missing option value", + "DdeStrs.Exe -- Invalid log level", + "DdeStrs.Exe -- Invalid number of test to execute", + "DdeStrs.Exe -- Invalid starting test number" + }; + + MessageBox(NULL,mpatszError[at],"Error:DdeStrs",MB_OK|MB_ICONEXCLAMATION); +} + +/***************************************************************************\ +* +* SysTime - This routine is intended to hide the differences between +* the 16 bit time routines and win 32. All time queries +* come through this point. +* +\***************************************************************************/ + +VOID SysTime( LPSYSTEMTIME lpst ) { + +#ifdef WIN32 + GetSystemTime( lpst ); +#else + +time_t t; +struct tm ttmm; +struct tm far *ptm=&ttmm; + + t=time(&t); + ptm=localtime(&t); + + lpst->wYear =ptm->tm_year; + lpst->wMonth =ptm->tm_mon; + lpst->wDayOfWeek =ptm->tm_wday; + lpst->wDay =ptm->tm_yday; + lpst->wHour =ptm->tm_hour; + lpst->wMinute =ptm->tm_min; + lpst->wSecond =ptm->tm_sec; + lpst->wMilliseconds =0; + +#endif + +} + +/************************** Private Function ****************************\ +* +* ParseCommandLine - This routine controls parsing the command line and +* initializing command line settings. +* +\**************************************************************************/ + +BOOL ParseCommandLine( HWND hwnd, LPSTR lpcmd ) { +SYSTEMTIME t; +LPSYSTEMTIME lptime=&t; +LONG lflags=0L; +INT i,nThrd,num,nFmts; +BOOL fSelect=FALSE; + +#ifdef WIN32 +LPCRITICAL_SECTION lpcs; +HANDLE hmem; +#endif + + // Defaults + + SetWindowLong(hwnd,OFFSET_FLAGS,FLAG_AUTO); + SetWindowLong(hwnd,OFFSET_RUNTIME,_1WEEKEND); + SetWindowLong(hwnd,OFFSET_STRESS,5L); + SetWindowLong(hwnd,OFFSET_DELAY,(100-GetWindowLong(hwnd,OFFSET_STRESS))*DELAY_METRIC); + SetWindowLong(hwnd,OFFSET_TIME_ELAPSED,0L); + SetWindowLong(hwnd,OFFSET_THRDCOUNT,1L); + SetWindowLong(hwnd,OFFSET_CRITICALSECT,0L); + + if(!get_cmd_arg(hwnd,lpcmd)) + return FALSE; + + // We need to make a change at this point for the + // default client/server settings. If at this point + // fClient==fServer==FALSE then we want to turn on + // both of these as the default. + + if(!fClient && !fServer) { + fClient=TRUE; + fServer=TRUE; + } + + // We need to check to see if specific formats where + // specified. If not then select all of them. + + nFmts=0; + for(i=0;i<NUM_FORMATS;i++) + if(iAvailFormats[i]) { + nFmts=nFmts++; + fSelect=TRUE; + } + + if(!fSelect) { + for(i=0;i<NUM_FORMATS;i++) iAvailFormats[i]=1; + nFmts=NUM_FORMATS; + } + + // We have now read all of the command line. Make needed adjustment + // to the delay as needed by addtional threads. + + // This adjustment code works with the routine SetStress. It + // does not simply recalculate values. A change to SetStress will + // cause changes in the final value. + + lflags=GetWindowLong(hwnd,OFFSET_FLAGS); + if(!(lflags&FLAG_USRDELAY)) { + + num=(INT)GetWindowLong(hwnd,OFFSET_DELAY); + nThrd=(INT)GetWindowLong(hwnd,OFFSET_THRDCOUNT); + + // 200 is the base value for basic overhead. + + num=(200)+(num*(nThrd*nThrd)*nFmts); + + SetWindowLong(hwnd,OFFSET_DELAY,num); + } + + SetWindowLong(hwnd,OFFSET_BASE_DELAY,GetWindowLong(hwnd,OFFSET_DELAY)); + + // We need to know the starting time to calculate + // time to quit test. + + SysTime(lptime); + + SetWindowLong(hwnd,OFFSET_STARTTIME_SEC,lptime->wSecond); + SetWindowLong(hwnd,OFFSET_STARTTIME_MIN,lptime->wMinute); + SetWindowLong(hwnd,OFFSET_STARTTIME_HOUR,lptime->wHour); + SetWindowLong(hwnd,OFFSET_STARTTIME_DAY,lptime->wDay); + + SetWindowLong(hwnd,OFFSET_LAST_MIN,lptime->wMinute); + SetWindowLong(hwnd,OFFSET_LAST_HOUR,lptime->wHour); + SetWindowLong(hwnd,OFFSET_TIME_ELAPSED,0L); + +#ifdef WIN32 + /* Setup our critical section if in multi-thread mode */ + + lflags=GetWindowLong(hwnd,OFFSET_FLAGS); + if(lflags&FLAG_MULTTHREAD) { + hmem=GetMemHandle(sizeof(CRITICAL_SECTION)); + lpcs=GlobalLock(hmem); + + InitializeCriticalSection(lpcs); + + GlobalUnlock(hmem); + SetWindowLong(hwnd,OFFSET_CRITICALSECT,(LONG)hmem); + } +#endif + + return TRUE; + +} + +/***************************************************************************\ +* +* SetupArgv - This is a conversion routine to go from the window worlds +* command line format to the more standard argv, argc +* format. The routine get_cmd_arg was setup for the +* argv/argc format. +* +\***************************************************************************/ + +int SetupArgv( char *argv[], char *buff, LPSTR cmdline ) +{ +int i=1; + + while( *cmdline != '\0' ) { + argv[i] = &buff[0]; + while ( *cmdline != ' ' && *cmdline != '\0') + *buff++ = *cmdline++; + *buff++='\0'; + while(*cmdline == ' ') cmdline++; + i++; + } + + return i; + +} + +/***************************************************************************\ +* +* get_cmd_arg - This routine parses a argv\argc formatted command +* line and stores away the values. +* +\***************************************************************************/ + +BOOL PASCAL get_cmd_arg( HWND hwnd, LPSTR cmdline ) { + +/* This function parses the command line for valid options. TRUE is + returned if all of the options are valid; otherwise, FALSE is returned. */ + +char *pch; +int iarg; +unsigned at = AT_SWITCH; +unsigned num; +int argc; +char *argv[10]; +char buff[200]; +LONG lflags=0L; + +#ifdef WIN32 +int nThrd; +#endif + + FixForStressPercentage(hwnd,cmdline); + FixForNetDdeStartup(hwnd,cmdline); + + argc = SetupArgv( argv, buff, cmdline ); + + /* Iterate over the arguments in the command line. */ + iarg=1; + while(iarg<argc && argv[iarg]!='\0') { + + /* Get the next argument. */ + pch = argv[iarg]; + + /* Process the argument depending upon the arguement + * type we are looking for. + */ + + switch (at) { + + case AT_SWITCH: + + /* All options begin with a switch character. */ + + if (*pch != '-' && *pch != '/') { + InitArgsError(hwnd,0); + return FALSE; + } + + /* Skip over the switch character. */ + pch++; + + /* Look for an option character. */ + do { + switch (*pch) { + case 'a': + /* Run the test in the background */ + lflags=GetWindowLong(hwnd,OFFSET_FLAGS); + SetWindowLong(hwnd,OFFSET_FLAGS,FLAGON(lflags,FLAG_APPOWNED)); + break; + + case 'p': + /* Run the test in the background */ + lflags=GetWindowLong(hwnd,OFFSET_FLAGS); + SetWindowLong(hwnd,OFFSET_FLAGS,FLAGON(lflags,FLAG_PAUSE_BUTTON|FLAG_PAUSE)); + break; + + case '?': + /* Give brief help. For more detailed information see ddestrs.txt in source directory */ + MessageBox(NULL,"DdeStrs Options...\r\n-#% stress\r\n-e# delay\r\n-t# run time\r\n-d debug\r\n-a appowned\r\n-s server\r\n-c client\r\n-f# format\r\n-nNAME netdde\r\n-i# threads\r\n-p pause\r\n\nSee DdeStrs.Txt","DdeStrs Help",MB_OK); + return FALSE; + break; + + + case 'b': + /* Run the test in the background */ + lflags=GetWindowLong(hwnd,OFFSET_FLAGS); + SetWindowLong(hwnd,OFFSET_FLAGS,FLAGON(lflags,FLAG_BACKGROUND)); + break; + + case 'l': + /* Set the name of the log file. */ + if (*(++pch) == '\0') { + /* The next argument should be a filename. */ + at = AT_FILE; + goto NextArg; + } + + case 'c': + /* This is a client */ + fClient = TRUE; + break; + + case 's': + /* This is a server */ + fServer = TRUE; + break; + + case 'i': + + /* The next argument should be the number of threads (w32 only) The + range for this = [1...5] */ +#ifdef WIN32 + lflags=GetWindowLong(hwnd,OFFSET_FLAGS); + SetWindowLong(hwnd,OFFSET_FLAGS,FLAGON(lflags,FLAG_MULTTHREAD)); +#endif + at = AT_THRD; + goto ParseNumber; + + case 'x': + /* The next argument should be the stress level. */ + at = AT_STRESS; + goto ParseNumber; + + case 'e': + /* The next argument is the delay in milliseconds */ + lflags=GetWindowLong(hwnd,OFFSET_FLAGS); + SetWindowLong(hwnd,OFFSET_FLAGS,FLAGON(lflags,FLAG_USRDELAY)); + at = AT_DELAY; + goto ParseNumber; + + case 'd': + /* The next argument is whether we are in debug mode */ + lflags=GetWindowLong(hwnd,OFFSET_FLAGS); + SetWindowLong(hwnd,OFFSET_FLAGS,FLAGON(lflags,FLAG_DEBUG)); + break; + + case 'n': + /* Process the network name */ + pch++; + + while( *pch==' ' || + *pch=='\\') pch++; + + pszNetName=GetMem(MAX_TITLE_LENGTH,&hmemNet); + pszNetName=TStrCpy(pszNetName,pch); + + lflags=GetWindowLong(hwnd,OFFSET_FLAGS); + SetWindowLong(hwnd,OFFSET_FLAGS,FLAGON(lflags,FLAG_NET)); + + while(*pch!='\0') { + pch++; + } + + pch--; + + break; + + case 'f': + at = AT_FORMAT; + goto ParseNumber; + + case 't': + lflags=GetWindowLong(hwnd,OFFSET_FLAGS); + SetWindowLong(hwnd,OFFSET_FLAGS,FLAGON(lflags,FLAG_TIME)); + + /* The next argument is the time (in minutes) + to run the test. */ + + at = AT_TIME; + goto ParseNumber; + + default: + InitArgsError(hwnd,0); + return FALSE; + + } // switch + + } while (*(++pch) != '\0'); // do-while loop + + break; + + case AT_FILE: + + /* The next argument should be a switch. */ + at = AT_SWITCH; + + break; + +ParseNumber: + /* Does this arg have the number? */ + if (*(++pch) == '\0') goto NextArg; + + case AT_STRESS: + case AT_DELAY: + case AT_TIME: + case AT_WND: + case AT_MSG: + case AT_THRD: + + /* Set the number of tests to run. */ + + if ((num = latoi(pch))==0) { + /* Indicate that an invalid number has been specified. */ + if(at!=AT_DELAY) { + InitArgsError(hwnd,0); + return FALSE; + } + } + + switch (at) { + case AT_FORMAT: + if (num>0 && num<=NUM_FORMATS) { + iAvailFormats[num-1]=1; + } + break; + + case AT_STRESS: + SetStress(hwnd,num); + break; + + case AT_DELAY: + SetWindowLong(hwnd,OFFSET_DELAY,num); + lflags=GetWindowLong(hwnd,OFFSET_FLAGS); + SetWindowLong(hwnd,OFFSET_FLAGS,FLAGON(lflags,FLAG_USRDELAY)); + break; + + case AT_TIME: + SetWindowLong(hwnd,OFFSET_RUNTIME,num); + break; + + case AT_THRD: +#ifdef WIN32 + if(num>THREADLIMIT) num=THREADLIMIT; + + // One is not really Mult-thread, shutoff the thread + // code and run in normal form. + + if(num==1) + { + lflags=GetWindowLong(hwnd,OFFSET_FLAGS); + + lflags=FLAGOFF(lflags,FLAG_MULTTHREAD); + lflags=FLAGON(lflags,FLAG_USRTHRDCOUNT); + + SetWindowLong(hwnd,OFFSET_FLAGS,lflags); + + SetWindowLong(hwnd,OFFSET_THRDCOUNT,num); + } + else { + SetWindowLong(hwnd,OFFSET_THRDCOUNT,num); + lflags=GetWindowLong(hwnd,OFFSET_FLAGS); + SetWindowLong(hwnd,OFFSET_FLAGS,FLAGON(lflags,FLAG_USRTHRDCOUNT)); + } +#endif + break; + + default: + InitArgsError(hwnd,0); + return FALSE; + break; + + } //switch (inside) + + /* The next argument should be a switch. */ + at = AT_SWITCH; + break; + + } // switch (outside) + +NextArg:; + iarg++; + } // While loop + + + /* Are we still looking for a filename or number? */ + if (at != AT_SWITCH) { + /* Tell the user about the filename or number not found. */ + InitArgsError(hwnd,0); + return FALSE; + } + + return TRUE; + +} // end get_cmd_args + +/***************************************************************************\ +* +* SetStress +* +\***************************************************************************/ + +BOOL SetStress(HWND hwnd, LONG num) { +LONG lflags; + +#ifdef WIN32 +LONG l; +#endif + +INT n; + + lflags=GetWindowLong(hwnd,OFFSET_FLAGS); + SetWindowLong(hwnd,OFFSET_STRESS,num); + +#ifdef WIN32 + + if(!(lflags&FLAG_USRTHRDCOUNT)) { + + l=S2L(DIV(num,20)+1); + if(num>9 && num<20) l++; + + if(l>5) l=5; + if(l<1) l=1; + + SetWindowLong(hwnd,OFFSET_THRDCOUNT,l); + + if(l>1) { + lflags=GetWindowLong(hwnd,OFFSET_FLAGS); + SetWindowLong(hwnd,OFFSET_FLAGS,FLAGON(lflags,FLAG_MULTTHREAD)); + } + } +#endif + + if(!(lflags&FLAG_USRDELAY)) { + n=(int)(100-num)*DELAY_METRIC; + SetWindowLong(hwnd,OFFSET_DELAY,n); + + // since dde messages have highest priority we don't + // want to swamp the system. Always have some + // minimal delay. + + if(n<10) { + SetWindowLong(hwnd,OFFSET_DELAY,10); + lflags=GetWindowLong(hwnd,OFFSET_FLAGS); + SetWindowLong(hwnd,OFFSET_FLAGS,FLAGOFF(lflags,FLAG_DELAYON)); + } + } + + return TRUE; +} + +/******************************************************************\ +* TStrLen +* 11/20/88 +* +* Finds the length of a string +\******************************************************************/ + +INT TStrLen( LPSTR pStr ) +{ +INT len = 0; + + while( *pStr++!='\0' ) len++; + + return( len ); +} + +/******************************************************************\ +* TStrCat +* 7/16/92 +* +* Appends source string to destination string. Source string and +* destination string must be zero terminated! +\******************************************************************/ + +LPSTR TStrCat( LPSTR dest, LPSTR source) +{ +LPSTR start_source; +LPSTR start_dest; +INT i=0; + + /* If we have a NULL pointer set destination to NULL and + continue */ + + if (!dest || !source) { + MessageBox(NULL,"TStrCat - NULL ptr for dest or source string!","Error : WmStress",MB_ICONEXCLAMATION); + return NULL; + } + + start_dest = dest; + start_source = source; + + while (*dest++!='\0' && i++<=MAX_TITLE_LENGTH) + ; + + TStrCpy(dest,source); + + source = start_source; + dest = start_dest; + + return( start_dest ); +} + +/*************************** Private Function ******************************\ +* +* TStrCmp +* +* Compares two NULL terminated strings ( returns TRUE if equal ) +* +\***************************************************************************/ + +BOOL TStrCmp(LPSTR s, LPSTR t) +{ + // Valid pointer? + + if ( !s && !t ) return TRUE; // If either is NULL then they should + if ( (!s&&t)||(s&&!t) ) // both be NULL. Otherwise error. + return FALSE; + + for (; *s == *t; s++, t++) // Compare strings + if (*s=='\0') + return TRUE; + + if ((*s-*t)== 0) return TRUE; + else return FALSE; +} + +/******************************************************************\ +* TStrCpy +* 11/20/88 +* +* Copies a string from source to destination +\******************************************************************/ + +LPSTR TStrCpy( LPSTR dest, LPSTR source) +{ +LPSTR start_source; +LPSTR start_dest; +INT i; + + /* If we have a NULL pointer set destination to NULL and + continue */ + + if(!source) { + dest=NULL; + return NULL; + } + + if (!dest) { + MessageBox(NULL,"TStrCpy - NULL ptr for dest!","Error:WmStress",MB_ICONEXCLAMATION); + return NULL; + } + + start_dest = dest; + start_source = source; + + i=0; + while (*dest++ = *source++){ + i++; + } + + source = start_source; + dest = start_dest; + + return( start_dest ); +} + +/***************************************************************************\ +* +* FixForStressPercentage - This is a fix for the command line -5%. The +* origional get_cmd_args() did not handle this +* case. This routine handles string modifications +* to the command line parse will be correct. +* +\***************************************************************************/ + +BOOL FixForStressPercentage(HWND hwnd, LPSTR lpszStart ) +{ +CHAR ac[6]; +INT i; +LPSTR lpsz,lpszdash; +BOOL bLastTime; + + lpsz =lpszStart; + lpszdash =NULL; + + ac[0]='x'; + + while(*lpsz!='\0') { + + if( *lpsz=='-') lpszdash=lpsz; + + if( *lpsz=='%') { + + if(lpszdash==NULL) return FALSE; + else lpsz=(LPSTR)(lpszdash+1); + + // Basically what we do hear is replace the '%' by an 'x' + // and shift characters...(-60% becomes -x60). + + i=0; + bLastTime=FALSE; + + while(!bLastTime) { + ac[i+1]=*lpsz; + if(*lpsz=='%') bLastTime=TRUE; + *lpsz=ac[i]; + lpsz++; + i++; + } + + } // if + + lpsz++; + + } // while + + return TRUE; + hwnd; + +} // FixForStressPercentage + +/***************************************************************************\ +* +* FixForNetDdeStartup - This is a fix for the command line "Test". The +* origional get_cmd_args() did not handle this +* case. This routine modifies the string from +* "Test" to "-s". +* +* The reason for this change is to make ddestrs.exe +* netdde aware for the startup situation. When +* netdde starts up the application is passed the topic +* name (in this case Test) to the application on the +* command line. +* +* NOTE!!! The below code relies on TOPIC="Test". If this has changed then +* update FixForNetDdeStartup() and IsTopicNameFromNetDde(). +* +\***************************************************************************/ + +BOOL FixForNetDdeStartup( HWND hwnd, LPSTR lpszStart ) +{ +INT i; +LPSTR lpsz; + + lpsz =lpszStart; + + i=1; + while(*lpsz!='\0') { + + // Important. I am relying on lpsz being the same + // exiting IsTopicNameFromNetDde as it was going in!!! + + if(IsTopicNameFromNetDde(lpsz,TOPIC)) { + + // We have one last check before we make the change. lpsz-2 + // must not be '-' or '/' and lpsz must not be 'n' or 'N'. + + // Are we at the 3rd char or later? We can't make this + // final check unless we have previous character to see. + + if(i>=3) { + if( *(lpsz-1)!='n' && + *(lpsz-1)!='N' && + *(lpsz-2)!='-' && + *(lpsz-2)!='/' ) + { + *lpsz='-'; + *(lpsz+1)='s'; // change "Test" to "-s " + *(lpsz+2)=' '; + *(lpsz+3)=' '; + } // if check for -,n,N,/ + + } // if i>=3 + else { + *lpsz='-'; + *(lpsz+1)='s'; // change "Test" to "-s " + *(lpsz+2)=' '; + *(lpsz+3)=' '; + } + + } // IsTopicName... + + lpsz++; + i++; // We use this to keep charater position. + + } // while + + return TRUE; + hwnd; + +} // FixForNetDdeStartup + +/***************************************************************************\ +* +* IsTopicNameFromNetDde +* +\***************************************************************************/ + +BOOL IsTopicNameFromNetDde(LPSTR lpsz, LPSTR lpszTopic ) +{ +LPSTR lpstr; + + // Check to see that string is >=4 characters not including NULL + // terminator. + + lpstr=lpsz; + + if(TStrLen(lpstr)<TStrLen(lpszTopic)) return FALSE; + + + // Is our topic string present. + + if(*lpsz!='T' && *lpsz!='t') { + return FALSE; + } + + if(*(lpsz+1)!='e' && *(lpsz+1)!='E') { + return FALSE; + } + + if(*(lpsz+2)!='s' && *(lpsz+2)!='S') { + return FALSE; + } + + if(*(lpsz+3)!='t' && *(lpsz+3)!='T') { + return FALSE; + } + + if(*(lpsz+4)!=' ' && *(lpsz+4)!='\0') { + return FALSE; + } + + return TRUE; + +} // IsTopicNameFromNetDde + +/************************** Private Function ****************************\ +* +* IsTimeExpired - This routine is called periodically to check if its +* time to quit. +* +\**************************************************************************/ + +BOOL IsTimeExpired( HWND hwnd ) { +LONG lrtime, lrtPMin, lrtPHour, lrt, l, ll; +SYSTEMTIME t; +LPSYSTEMTIME lptime=&t; +LONG lflags=0L; + + lflags=GetWindowLong(hwnd,OFFSET_FLAGS); + + if(!(lflags&FLAG_STOP)) { + // This is how long we should run. In minutes + + lrtime =GetWindowLong(hwnd,OFFSET_RUNTIME); + + // This is how long we have run. In minutes. + + lrt =GetWindowLong(hwnd,OFFSET_TIME_ELAPSED); + l=lrt; + + // Time at last check. + + lrtPMin =GetWindowLong(hwnd,OFFSET_LAST_MIN); + lrtPHour=GetWindowLong(hwnd,OFFSET_LAST_HOUR); + + SysTime(lptime); + + if(lrtPHour!=(LONG)(lptime->wHour)) { + + // Calc update minutes for the wrap case. + + lrt=(((_1HOUR-lrtPMin)+lptime->wMinute)+lrt); + + // We need to check for multiple hours since last + // update. + + if(lrtPHour>lptime->wHour) { + + // In case clock does not rap at 12:00. + + if(lptime->wHour>12) ll=lptime->wHour-12; + else ll=lptime->wHour; + + l=(12-lrtPHour)+ll; + } + else l=lptime->wHour-lrtPHour; + + if(l>1) { + lrt=lrt+((l-1)*_1HOUR); + } + + } + + else lrt=((lptime->wMinute-lrtPMin)+lrt); + + SetWindowLong(hwnd,OFFSET_LAST_MIN,(LONG)lptime->wMinute); + SetWindowLong(hwnd,OFFSET_LAST_HOUR,(LONG)lptime->wHour); + SetWindowLong(hwnd,OFFSET_TIME_ELAPSED,lrt); + + if(lptime->wMinute!=LOWORD(lrtPMin)) + UpdateCount(hwnd,OFFSET_TIME_ELAPSED,PNT); + + // if elapsed time > runtime time has expired. + + if(lrt>=lrtime) + return TRUE; + else return FALSE; + } + + // If we are already shutting down no need to trigger other WM_CLOSE + // messages. + + else return FALSE; + +} + +/*---------------------------------------------------------------------------*\ +| ASCII TO INTEGER +| This routine converts an ascii string to a decimal integer. +| +| created: 12-Oct-90 +| history: 12-Oct-90 <chriswil> created. +| +\*---------------------------------------------------------------------------*/ +int APIENTRY latoi(LPSTR lpString) +{ + int nInt,nSign; + + + if(*lpString == '-') + { + nSign = -1; + lpString++; + } + else + { + if(*lpString == '+') + lpString++; + nSign = 1; + } + + nInt = 0; + while(*lpString) + nInt = (nInt*10) + (*lpString++ - 48); + + return(nInt * nSign); +} + +/*****************************************************************************\ +| INTEGER TO ASCI +| This routine converts an decimal integer to an ascii string. +| +| created: 29-Jul-91 +| history: 29-Jul-91 <johnsp> created. +| +\*****************************************************************************/ +LPSTR FAR PASCAL itola(INT i, LPSTR lpsz) +{ +LPSTR lpsz_start; +INT irange=1; +INT id=0; + + lpsz_start=lpsz; // Keep track of the beginning of the + // string. + while (id=DIV(i,irange)>0) + irange=irange*10; + + irange=DIV(irange,10); + + if(i==0) { // If i==0 set string and we + *lpsz='0'; // will skip loop + lpsz++; + } + + while (irange>0) { + + id=DIV(i,irange); // Calculate character + *lpsz=(CHAR)(id+48); + + lpsz++; + i=i-(irange*id); // Adjust values for next time + irange=DIV(irange,10); // through the loop. + + } + + *lpsz='\0'; // Null terminate the string + + return lpsz_start; + +} diff --git a/private/mvdm/wow16/ddeml/tests/ddestrs/ddesorg.ico b/private/mvdm/wow16/ddeml/tests/ddestrs/ddesorg.ico Binary files differnew file mode 100644 index 000000000..65c6a7180 --- /dev/null +++ b/private/mvdm/wow16/ddeml/tests/ddestrs/ddesorg.ico diff --git a/private/mvdm/wow16/ddeml/tests/ddestrs/ddestrs.c b/private/mvdm/wow16/ddeml/tests/ddestrs/ddestrs.c new file mode 100644 index 000000000..e05745cb4 --- /dev/null +++ b/private/mvdm/wow16/ddeml/tests/ddestrs/ddestrs.c @@ -0,0 +1,1856 @@ +#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; + +} + + diff --git a/private/mvdm/wow16/ddeml/tests/ddestrs/ddestrs.def b/private/mvdm/wow16/ddeml/tests/ddestrs/ddestrs.def new file mode 100644 index 000000000..775c1543d --- /dev/null +++ b/private/mvdm/wow16/ddeml/tests/ddestrs/ddestrs.def @@ -0,0 +1,17 @@ +NAME DDESTRS + +DESCRIPTION 'Microsoft Windows DDE stress' +EXETYPE WINDOWS +STUB 'WINSTUB.EXE' + +CODE PRELOAD FIXED +DATA PRELOAD MOVEABLE MULTIPLE + +HEAPSIZE 4096 +STACKSIZE 4096 + +EXPORTS + MAINWNDPROC @1 + DISPWNDPROC @2 + WRAPPERCALLBACK @3 + diff --git a/private/mvdm/wow16/ddeml/tests/ddestrs/ddestrs.h b/private/mvdm/wow16/ddeml/tests/ddestrs/ddestrs.h new file mode 100644 index 000000000..192a2c3a9 --- /dev/null +++ b/private/mvdm/wow16/ddeml/tests/ddestrs/ddestrs.h @@ -0,0 +1,287 @@ +#ifdef WIN16 + +typedef struct _SYSTEMTIME { + WORD wYear; + WORD wMonth; + WORD wDayOfWeek; + WORD wDay; + WORD wHour; + WORD wMinute; + WORD wSecond; + WORD wMilliseconds; +} SYSTEMTIME, *PSYSTEMTIME, *LPSYSTEMTIME; + +#define GETCURRENTTHREADID() 1 + +#else + +#define GETCURRENTTHREADID() GetCurrentThreadId() + +#endif + +#define WHITE RGB(255,255,255) +#define GREEN RGB(0,128,128) +#define GREY RGB(192,192,192) +#define TOPIC "Test" + +extern HANDLE hExtraMem; + +#ifdef WIN32 +#define PNT_INTERVAL 60000 +#else +#define PNT_INTERVAL 30000 +#endif + +#define _5SEC 5000 // milliseconds +#define _1MIN 1 +#define _1HOUR 60 +#define _1DAY 1440 +#define _1WEEKEND 4320 +#define _1WEEK 10080 +#define SERVER 0 +#define CLIENT 1 + +#ifdef WIN16 +#define NUM_FORMATS 5 +#else +#define NUM_FORMATS 6 +#endif + +// The below offsets are used with Set/GetThreadLong() "THREAD" +// Offset defines cannot be interchanged between window +// and thread use because of collisions. + +#define OFFSET_IDINST 0 +#define OFFSET_HCONVLIST 4 +#define OFFSET_CSERVERCONVS 8 +#define OFFSET_HSERVERCONVS 12 +#define OFFSET_HAPPOWNED 16 +#define OFFSET_CCLIENTCONVS 20 +#define OFFSET_HWNDDISPLAY 24 +#define OFFSET_CLIENTTIMER 28 +#define OFFSET_SERVERTIMER 32 +#define DELAY_METRIC 2 + +#define EXTRA_THREAD_MEM OFFSET_SERVERTIMER+4 +#define S2L(s) (LONG)(MAKELONG((WORD)(s),0)) + +// The below offsets are used with Set/GetWindowLong() "WINDOW" + +#define OFFSET_FLAGS 0 +#define OFFSET_RUNTIME 4 +#define OFFSET_STARTTIME_SEC 8 +#define OFFSET_STARTTIME_MIN 12 +#define OFFSET_STARTTIME_HOUR 16 +#define OFFSET_STARTTIME_DAY 20 +#define OFFSET_LAST_MIN 24 +#define OFFSET_LAST_HOUR 28 +#define OFFSET_TIME_ELAPSED 32 +#define OFFSET_DELAY 36 +#define OFFSET_STRESS 40 +#define OFFSET_SERVER_CONNECT 44 +#define OFFSET_CLIENT_CONNECT 48 +#define OFFSET_CLIENT 52 +#define OFFSET_SERVER 56 + +#define OFFSET_THRDMAIN 60 // <== *** +#define OFFSET_THRD2 64 // <== *** Ordering here is relied +#define OFFSET_THRD3 68 // <== *** upon in the test. Keep +#define OFFSET_THRD4 72 // <== *** This group of values +#define OFFSET_THRD5 76 // <== *** in sequential order. +#define OFFSET_THRDMID 80 // <== *** +#define OFFSET_THRD2ID 84 // <== *** +#define OFFSET_THRD3ID 88 // <== *** +#define OFFSET_THRD4ID 92 // <== *** +#define OFFSET_THRD5ID 96 // <== *** +#define OFFSET_THRD2EVENT 100 // <== *** +#define OFFSET_THRD3EVENT 104 // <== *** +#define OFFSET_THRD4EVENT 108 // <== *** +#define OFFSET_THRD5EVENT 112 // <== *** + +#define OFFSET_CRITICALSECT 116 +#define OFFSET_THRDCOUNT 120 +#define OFFSET_EXTRAMEM 124 +#define OFFSET_DISPWNDHEIGHT 128 +#define OFFSET_BASE_DELAY 132 +#define OFFSET_MEM_ALLOCATED 136 + +#define WND OFFSET_MEM_ALLOCATED+4 + +#define ID_OFFSET 20 +#define INC 1 +#define DEC 0 +#define STP 2 +#define PNT 3 +#define ALL -1 + +#define ON 1 +#define OFF 0 + +#define AT_SWITCH 1 +#define AT_FILE 2 +#define AT_STRESS 3 +#define AT_DELAY 4 +#define AT_TIME 5 +#define AT_WND 6 +#define AT_MSG 7 +#define AT_FORMAT 8 +#define AT_THRD 9 + +#define FLAG_BACKGROUND 0x00000001 +#define FLAG_AUTO 0x00000002 +#define FLAG_TIME 0x00000004 +#define FLAG_STOP 0x00000008 +#define FLAG_LOG 0x00000010 +#define FLAG_USRWNDCOUNT 0x00000020 +#define FLAG_USRMSGCOUNT 0x00000040 +#define FLAG_USRDELAY 0x00000080 +#define FLAG_DEBUG 0x00000100 +#define FLAG_CHARINFO 0x00000200 +#define FLAG_DELAYON 0x00000400 +#define FLAG_TEST_MSG_ON 0x00000800 +#define FLAG_MSGDELAYON 0x00001000 +#define FLAG_APPOWNED 0x00002000 +#define FLAG_MULTTHREAD 0x00004000 + +#define FLAG_THRD2 0x00008000 +#define FLAG_THRD3 0x00010000 +#define FLAG_THRD4 0x00020000 +#define FLAG_THRD5 0x00040000 + +#define FLAG_NET 0x00080000 +#define FLAG_SYNCPAINT 0x00100000 +#define FLAG_USRTHRDCOUNT 0x00200000 +#define FLAG_PAUSE_BUTTON 0X00400000 +#define FLAG_PAUSE 0X00800000 + +#define THREADLIMIT 5 + +#define STD_EXIT 1 +#define ABNORMAL_EXIT 0 + +#define FLAGON(a,b) (LONG)(a|b) +#define FLAGOFF(a,b) (LONG)(a&(~b)) + +//#define MAX_SERVER_HCONVS 1000 +#define MAX_SERVER_HCONVS 500 + +#define IDR_ICON 1 +#define IDR_MENU 2 +#define IDM_DIE 100 + +#define DIGITS_IN_TENMILL 8 +#define BLANK_SPACE 3 +#define LONGEST_LINE 15 + +#define NUM_COLUMNS (LONGEST_LINE+BLANK_SPACE+DIGITS_IN_TENMILL) +#define NUM_ROWS 16 +#define MAX_TITLE_LENGTH 100 + +#define TXT 0 +#define DIB 1 +#define BITMAP 2 +#define ENHMETA 3 +#define METAPICT 4 +#define PALETTE 5 + +#define EXIT_THREAD WM_USER+6 +#define START_DISCONNECT WM_USER+7 + +#include "globals.h" + +/* + * Prototypes + */ + +/* + * ddestrs.c + */ + +LONG FAR PASCAL MainWndProc(HWND hwnd, UINT message, WPARAM wParam, LONG lParam); + +VOID InitArgsError(HWND,unsigned); +VOID SysTime(LPSYSTEMTIME); +BOOL ParseCommandLine(HWND,LPSTR); +int SetupArgv( char **, char *, LPSTR); +BOOL PASCAL get_cmd_arg(HWND,LPSTR); +BOOL IsTimeExpired(HWND); + +INT DIV(INT,INT); + +BOOL TStrCmp(LPSTR,LPSTR); +LPSTR TStrCpy(LPSTR,LPSTR); +LPSTR TStrCat(LPSTR,LPSTR); +INT TStrLen(LPSTR); + +LPSTR FAR PASCAL itola(int,LPSTR); +int APIENTRY latoi(LPSTR); + +BOOL DOut(HWND,LPSTR,LPSTR,INT); +BOOL EOut(LPSTR); + + +#ifdef WIN32 +BOOL ThreadShutdown(VOID); +BOOL ThreadDisconnect(VOID); +#endif + +#define DDEMLERROR(a) EOut(a) +#define LOGDDEMLERROR(a) EOut(a) + + +/* + * client.c + */ + +void CALLBACK TimerFunc(HWND,UINT,UINT,DWORD); +VOID PaintClient(HWND hwnd, PAINTSTRUCT *pps); +VOID ReconnectList(VOID); +BOOL InitClient(VOID); +VOID CloseClient(VOID); + +/* + * server.c + */ + +HDDEDATA RenderHelp_Text(HDDEDATA hData); +BOOL PokeTestItem_Text(HDDEDATA hData); +HDDEDATA RenderTestItem_Text(HDDEDATA hData); +BOOL PokeTestItem_DIB(HDDEDATA hData); +HDDEDATA RenderTestItem_DIB(HDDEDATA hData); +BOOL PokeTestItem_BITMAP(HDDEDATA hData); +HDDEDATA RenderTestItem_BITMAP(HDDEDATA hData); +BOOL PokeTestItem_METAPICT(HDDEDATA hData); +HDDEDATA RenderTestItem_METAPICT(HDDEDATA hData); +BOOL PokeTestItem_ENHMETA(HDDEDATA hData); +HDDEDATA RenderTestItem_ENHMETA(HDDEDATA hData); +BOOL PokeTestItem_PALETTE(HDDEDATA hData); +HDDEDATA RenderTestItem_PALETTE(HDDEDATA hData); +HINSTANCE GetHINSTANCE(HWND); + +BOOL Execute(HDDEDATA hData); +VOID PaintServer(HWND hwnd, PAINTSTRUCT *pps); +HDDEDATA FAR PASCAL CustomCallback(UINT wType, UINT wFmt, HCONV hConv, HSZ hsz1, + HSZ hsz2, HDDEDATA hData, DWORD dwData1, DWORD dwData2); + +#ifdef WIN32 +VOID ThreadWait(HWND); +DWORD SecondaryThreadMain(DWORD); +BOOL ThreadInit(HWND); +#endif + +LONG SetFlag(HWND,LONG,INT); +LONG SetCount(HWND,INT,LONG,INT); +LPSTR GetMem(INT, LPHANDLE); +BOOL FreeMem(HANDLE); +BOOL FreeMemHandle(HANDLE); +HANDLE GetMemHandle(INT); +LONG SetThreadLong(DWORD,INT,LONG); +LONG GetThreadLong(DWORD,INT); +BOOL FreeThreadExtraMem(void); +BOOL CreateThreadExtraMem(INT,INT); +BOOL InitThreadInfo(DWORD); +BOOL FreeThreadInfo(DWORD); +INT IDtoTHREADNUM(DWORD); +HWND CreateDisplayWindow(HWND,INT); +LONG GetCurrentCount(HWND,INT); + diff --git a/private/mvdm/wow16/ddeml/tests/ddestrs/ddestrs.ico b/private/mvdm/wow16/ddeml/tests/ddestrs/ddestrs.ico Binary files differnew file mode 100644 index 000000000..035bcc11b --- /dev/null +++ b/private/mvdm/wow16/ddeml/tests/ddestrs/ddestrs.ico diff --git a/private/mvdm/wow16/ddeml/tests/ddestrs/ddestrs.rc b/private/mvdm/wow16/ddeml/tests/ddestrs/ddestrs.rc new file mode 100644 index 000000000..b5090896a --- /dev/null +++ b/private/mvdm/wow16/ddeml/tests/ddestrs/ddestrs.rc @@ -0,0 +1,13 @@ +#include <windows.h> +#include "ddestrs.h" + +IDR_ICON ICON ddestrs.ico + + +IDR_MENU MENU +BEGIN + POPUP "&Options" + BEGIN + MENUITEM "&Die!", IDM_DIE + END +END diff --git a/private/mvdm/wow16/ddeml/tests/ddestrs/ddestrs.txt b/private/mvdm/wow16/ddeml/tests/ddestrs/ddestrs.txt new file mode 100644 index 000000000..d87d32c93 --- /dev/null +++ b/private/mvdm/wow16/ddeml/tests/ddestrs/ddestrs.txt @@ -0,0 +1,110 @@ +The document breifly describes DdeStrs.exe. + +DdeStrs is intended to exercise and stress Dde/Ddeml. + +Some areas exercised in the test are ... + + o Async/fAckRequest advise loops + o Async executes + o CF_TEXT, CF_DIB, CF_BITMAP, CF_METAFILEPICT, CF_PALETTE, + and CF_ENHMETAFILE (w32 only) formats. + o DdeConnectList/DdeDisconnectList + o AppOwned handles [when -a option used] + o Variable client/server connects (number of instances running + of ddestrs.exe) + o Cross process/In process and multithread communication. + o System Timers + + +The command line options are ... + +DdeStrs [-#%,-e#,-t#,-d,-a,-s,-c,-f#,-nNAME,-i#,-p,-?] + + where -#% allow the user to specify the intensity of + the run (# = [1...100]) and can be read as stress + percentage. 1 being low stress 100 being high stress. + + where -e# allows override of the delay set by the stress + level. -e0 is usefull if the stress test is the only one + running and it is desirable for the test to cover ground + (number of windows, classes, and messages that are + exercised). # is in milliseconds. + + where -t# specifies the number of minutes for the test to run. At + the end of # minutes the test will shutdown. Default is 4320 min + (About a weekend). Test can also be exited manually at any + point. + + where -d selects debug mode. This mode of operation displays + additional test information and outputs failures to + the debug terminal. This mode is intended for debugging + DdeStrs failures and not for use in public stress runs. + + where -a specifies to use AppOwned handle for data communications. + + where -s specifies that this instance is to run as server only + [default is -s -c]. + + where -c specifies that this instance is to run as client only. + [default is -s -c]. + + where -f# allow specific formats to be used. Default is all + formats. If any specific formats are specified then only + to formats will be used in the communication. + + [Ex - ddestrs -f1 -f2] will only use formats 1 and 2. + + Formats 1 CF_TEXT + 2 CF_DIB + 3 CF_BITMAP + 4 CF_ENHMETAFILE (w32 only) + 5 CF_METAFILEPICT + 6 CF_PALETTE + + where -nNAME specifies the computer name to connect to. This + is used for netdde and only needs to be specified on client + applications. NAME=servername, Example '-njohnsp1' for + computer \\johnsp1. Use Ddeshare.exe (w31 resources kit or + Nt sdk) to setup the dde share enabling netdde to work. DdeStrs + Service Name=DdeStrs, Topic=Test, and permissions must be + change or greater (ddestrs.exe uses executes). + + where -i# specifies the number of threads to execute. # can + be in the range [1..5]. This option is only available + for Win Nt. + + where -p specifies pause before data update. With this specified the user can + manually start executes and advise updates. With this connections are established, but + no data is passed until manually started. DdeStrs adds a 'pause' button to allow stress + to be started and stopped. Default is NO -p. + + where -? brings up a brief help list of DdeStrs Options. + +Test Usage ... + + Ddestrs will communicate with multiple copies of itself. Each + new instance of ddestrs started will cause other instances to + connect to all running copies available for conversation. This + allows the stress level to be tailored both by the -#% and + by the number of copies of the test running. + +Focus Test Api ... + +DdeQueryNextServer +DdeClientTransaction +DdeDisconnectList +DdeConnectList +DdeAccessData +DdeAddData +DdePostAdvise +DdeDisconnect +DdeUnaccessData +DdeInitialize +DdeNameService +DdeCreateStringHandle +DdeUninitialize +DdeFreeStringHandle +DdeCmpStringHandles +DdeQueryConvInfo +DdeCreateDataHandle +DdeFreeDataHandle diff --git a/private/mvdm/wow16/ddeml/tests/ddestrs/globals.c b/private/mvdm/wow16/ddeml/tests/ddestrs/globals.c new file mode 100644 index 000000000..8dc7c2b3e --- /dev/null +++ b/private/mvdm/wow16/ddeml/tests/ddestrs/globals.c @@ -0,0 +1,106 @@ + +#include <windows.h> +#include <port1632.h> +#include <ddeml.h> +#include "wrapper.h" +#include "ddestrs.h" + +/* Truley global variables */ + +CHAR szClass[] = "DdeStrs"; +int cyText = 0; +int cxText = 0; +BOOL fClient = FALSE; +BOOL fServer = FALSE; +HINSTANCE hInst; + +HWND hwndMain; +CHAR szExecDie[] = "Die"; +CHAR szExecDisconnect[] = "Disconnect"; +CHAR szExecRefresh[] = "Refresh"; + +// This array contains storage for each supported +// format (CF_TEXT,CF_BITMAP,CF_DIB,..CF_ENHMETAFILE) + +INT iAvailFormats[] = { 0, 0, 0, 0, 0, 0 }; + +/* + * Service tables - read bottom up + */ +DDEFORMATTBL TestItemFormats[] = { + { + "TEXT", + CF_TEXT, + 0, + PokeTestItem_Text, + RenderTestItem_Text + }, + { + "DIB", + CF_DIB, + 0, + PokeTestItem_DIB, + RenderTestItem_DIB + }, + { + "BITMAP", + CF_BITMAP, + 0, + PokeTestItem_BITMAP, + RenderTestItem_BITMAP + }, +#ifdef WIN32 + { + "ENHMETAFILE", + CF_ENHMETAFILE, + 0, + PokeTestItem_ENHMETA, + RenderTestItem_ENHMETA + }, +#endif + { + "METAFILEPICT", + CF_METAFILEPICT, + 0, + PokeTestItem_METAPICT, + RenderTestItem_METAPICT + }, + { + "PALETTE", + CF_PALETTE, + 0, + PokeTestItem_PALETTE, + RenderTestItem_PALETTE + } +}; + +DDEITEMTBL Items[] = { + { + "TestItem", + 0, + sizeof(TestItemFormats) / sizeof(DDEFORMATTBL), + 0, + TestItemFormats + } +}; + +DDETOPICTBL Topics[] = { + { + TOPIC, + 0, + sizeof(Items) / sizeof(DDEITEMTBL), + 0, + Items, + Execute + } +}; + +DDESERVICETBL ServiceInfoTable[] = { + { + "DdeStrs", + 0, + sizeof(Topics) / sizeof(DDETOPICTBL), + 0, + Topics + } +}; diff --git a/private/mvdm/wow16/ddeml/tests/ddestrs/globals.h b/private/mvdm/wow16/ddeml/tests/ddestrs/globals.h new file mode 100644 index 000000000..b1ccda8ee --- /dev/null +++ b/private/mvdm/wow16/ddeml/tests/ddestrs/globals.h @@ -0,0 +1,19 @@ + +extern CHAR szClass[]; +extern int cyText; +extern int cxText; +extern BOOL fClient; +extern BOOL fServer; +extern HINSTANCE hInst; +extern HCONV pServerhConvs[MAX_SERVER_HCONVS]; +extern HWND hwndMain; +extern CHAR szExecDie[]; +extern CHAR szExecDisconnect[]; +extern CHAR szExecRefresh[]; +extern INT iAvailFormats[]; + +DDEFORMATTBL TestItemFormats[]; +DDEITEMTBL Items[]; +DDETOPICTBL Topics[]; +DDESERVICETBL ServiceInfoTable[]; + diff --git a/private/mvdm/wow16/ddeml/tests/ddestrs/makefile b/private/mvdm/wow16/ddeml/tests/ddestrs/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/mvdm/wow16/ddeml/tests/ddestrs/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/mvdm/wow16/ddeml/tests/ddestrs/makefile.dos b/private/mvdm/wow16/ddeml/tests/ddestrs/makefile.dos new file mode 100644 index 000000000..c7c1599a1 --- /dev/null +++ b/private/mvdm/wow16/ddeml/tests/ddestrs/makefile.dos @@ -0,0 +1,50 @@ +# +# Test makefile + +!ifdef WIN31 +EXEFLAGS=-AM -Gsw -Od -Ziep -W3 -DWIN16 -DWIN31 -DUSECOMM -DWIN +!else +EXEFLAGS=-AS -FPi -Gcw -Os -Ziepd -W3 -DWIN16 -DWIN +!endif + +TEST =ddestrs +RCFILE =ddestrs +S1 =cmdln +S2 =client +S3 =$(TEST) +S4 =globals +S5 =server +S6 =wrapper +OBJ =$(S1).obj $(S2).obj $(S3).obj $(S4).obj $(S5).obj $(S6).obj + +# +# Stress Test +# + +all: $(TEST).exe + +$(RCFILE).res: $(RCFILE).rc + rc -r $(RCFILE).rc + +$(S1).obj: $(S1).c $(S3).h $(S6).h + cl -c $(EXEFLAGS) $(S1).c + +$(S2).obj: $(S2).c $(S3).h $(S6).h + cl -c $(EXEFLAGS) $(S2).c + +$(S3).obj: $(S3).c $(S3).h $(S6).h + cl -c $(EXEFLAGS) $(S3).c + +$(S4).obj: $(S4).c $(S3).h $(S6).h + cl -c $(EXEFLAGS) $(S4).c + +$(S5).obj: $(S5).c $(S3).h $(S6).h + cl -c $(EXEFLAGS) $(S5).c + +$(S6).obj: $(S6).c $(S3).h $(S6).h + cl -c $(EXEFLAGS) $(S6).c + +$(TEST).exe: $(OBJ) $(TEST).def $(RCFILE).res + link /map/li/co $(OBJ)/AL:16,$(TEST).exe,, /NOE /NOD libw ddeml mlibcew,$(TEST).def + mapsym $(TEST) + rc $(RCFILE).res $(TEST).exe diff --git a/private/mvdm/wow16/ddeml/tests/ddestrs/mk.cmd b/private/mvdm/wow16/ddeml/tests/ddestrs/mk.cmd new file mode 100644 index 000000000..7fbb62b49 --- /dev/null +++ b/private/mvdm/wow16/ddeml/tests/ddestrs/mk.cmd @@ -0,0 +1 @@ +build -cl ddestrs diff --git a/private/mvdm/wow16/ddeml/tests/ddestrs/mk4dos.cmd b/private/mvdm/wow16/ddeml/tests/ddestrs/mk4dos.cmd new file mode 100644 index 000000000..1cc3f8bff --- /dev/null +++ b/private/mvdm/wow16/ddeml/tests/ddestrs/mk4dos.cmd @@ -0,0 +1,13 @@ +@echo off +if "%1"=="" goto bld +del *.dll +del *.sym +del *.map +del *.obj +del *.bak +del *.res +del *.lnk +goto done +:bld +nmake -f makefile.dos +:done diff --git a/private/mvdm/wow16/ddeml/tests/ddestrs/runddes.bat b/private/mvdm/wow16/ddeml/tests/ddestrs/runddes.bat new file mode 100644 index 000000000..d68805551 --- /dev/null +++ b/private/mvdm/wow16/ddeml/tests/ddestrs/runddes.bat @@ -0,0 +1,12 @@ +start ddestrs.exe -10%% -e35000 +sleep 30 + +ddestrs.exe -c -e13000 -t10 +sleep 10 + +:loop +start ddestrs.exe -t3 -s -a +sleep 15 +ddestrs.exe -c -e13000 -t10 +sleep 20 +goto loop diff --git a/private/mvdm/wow16/ddeml/tests/ddestrs/server.c b/private/mvdm/wow16/ddeml/tests/ddestrs/server.c new file mode 100644 index 000000000..56f1d2280 --- /dev/null +++ b/private/mvdm/wow16/ddeml/tests/ddestrs/server.c @@ -0,0 +1,1372 @@ + +#include <windows.h> +#include <port1632.h> +#include <ddeml.h> +#include <string.h> +#include "wrapper.h" +#include "ddestrs.h" + +extern BOOL UpdateCount(HWND,INT,INT); +BOOL Balance(INT); + +/* + * Service routines + */ + +/*************************** Private Function ******************************\ + +GetHINSTANCE + +\***************************************************************************/ + +HINSTANCE GetHINSTANCE( HWND hwnd ) { +HINSTANCE hInstance; + +#ifdef WIN32 + hInstance=(HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE); +#else + hInstance=(HINSTANCE)GetWindowWord(hwnd,GWW_HINSTANCE); +#endif + + return hInstance; + +} + +//***************************************************************************** +//************************** DispWndProc ************************** +//***************************************************************************** + +LONG FAR PASCAL DispWndProc( HWND hwnd , UINT msg, WPARAM wp, LONG lp) { + + return DefWindowProc(hwnd,msg,wp,lp); + +} + +/*************************** Private Function ******************************\ +* +* CreateDisplayWindow +* +\***************************************************************************/ + +HWND CreateDisplayWindow( HWND hwndParent, int nPosIndex ) { +WNDCLASS wc,wcc; +LPWNDCLASS lpWndClass=&wc; +HWND hwnd; +RECT r; +int stpy,stpx,cy; +char sz[100]; +LPSTR lpstr=&sz[0]; + +#ifdef WIN32 +LPCTSTR lpsz; +#else +LPSTR lpsz; +#endif + +char szname[100]; + + strcpy(&szname[0],"Display Window"); + + wc.style = 0; + wc.lpfnWndProc = DispWndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = GetHINSTANCE(hwndParent); + wc.hIcon = LoadIcon(NULL,IDI_EXCLAMATION ); + wc.hCursor = LoadCursor(NULL,IDC_ARROW ); + wc.lpszMenuName = NULL; + wc.lpszClassName = "Display Window"; + wc.hbrBackground = CreateSolidBrush(RGB(0,255,255)); + + lpsz=(LPSTR)wc.lpszClassName; + + if(!GetClassInfo(wc.hInstance,lpsz,&wcc)) { + RegisterClass(lpWndClass); + } + + GetClientRect(hwndParent,&r); + + stpx =r.right-r.left; + stpy =((r.bottom-r.top)/3); + + switch(nPosIndex) { + case 1: cy=r.bottom-(3*cyText); + break; + case 2: cy=r.bottom-(6*cyText); + break; + case 3: cy=r.bottom-(9*cyText); + break; + case 4: cy=r.bottom-(12*cyText); + break; + case 5: cy=r.bottom-(15*cyText); + break; + default: cy=r.bottom-(18*cyText); + break; + } + + if (!IsWindow(hwndParent)) DOut((HWND)NULL,"DdeStrs.exe -- ERR:Bad parent hwnd=%u!\r\n",0,(LONG)hwndParent); + + hwnd = CreateWindowEx(WS_EX_DLGMODALFRAME, + "Display Window", + &szname[0], + WS_CHILD|WS_VISIBLE|WS_CAPTION|WS_DISABLED, + 0, + cy, + stpx, + 3*cyText, + hwndParent, + NULL, + lpWndClass->hInstance, + NULL ); + + if ( !IsWindow(hwnd) ) + { + DDEMLERROR("DdeStrs.Exe -- ERR:Display window not created\r\n"); + UnregisterClass("Display Window",wc.hInstance); + } + + return hwnd; + +} + +BOOL PokeTestItem_Text( +HDDEDATA hData) +{ +LPBYTE lpData; +HDC hdc; +HBRUSH hBrush; +PAINTSTRUCT ps; +RECT rc; +DWORD cbData; +HWND hwndDisplay; + + Balance(OFFSET_CLIENT); + + hwndDisplay=(HWND)GetThreadLong(GETCURRENTTHREADID(),OFFSET_HWNDDISPLAY); + SetWindowText(hwndDisplay,"Client - CF_TEXT"); + + lpData = (LPBYTE) DdeAccessData( hData, &cbData ); + + hdc = GetDC(hwndDisplay); + if(!hdc) { + DDEMLERROR("DdeStrs.Exe -- ERR:NULL hdc ret from GetDC (client:CF_TEXT)!\r\n"); + DdeUnaccessData(hData); //JOHNSP:CHANGE + return 0; + } + + hBrush=CreateSolidBrush(WHITE); + if(!hBrush) { + DDEMLERROR("DdeStrs.Exe -- ERR:NULL hBrush ret from CreateSolidBrush (client:CF_TEXT)!\r\n"); + DdeUnaccessData(hData); //JOHNSP:CHANGE + EndPaint(hwndDisplay,&ps); + return 0; + } + + GetClientRect(hwndDisplay,&rc); + + FillRect(hdc,&rc,hBrush); + DeleteObject(hBrush); + + DrawText(hdc, lpData, -1, &rc, DT_LEFT|DT_TOP); + ReleaseDC(hwndDisplay,hdc); + + DdeUnaccessData(hData); //JOHNSP:CHANGE + + return(TRUE); + +} + +BOOL PokeTestItem_DIB( +HDDEDATA hData) +{ +HWND hwnd; +HDC hdc; +RECT r; +INT width,height; +LPBITMAPINFO lpbitinfo; +LPBYTE lpbits; +HANDLE hmem; +LPBYTE lpData; +DWORD cbData; +LPBYTE lp; +int iexRGB; + + Balance(OFFSET_CLIENT); + + lpData = (LPBYTE) DdeAccessData( hData, &cbData ); + + hwnd=(HWND)GetThreadLong(GETCURRENTTHREADID(),OFFSET_HWNDDISPLAY); + SetWindowText(hwnd,"Client - CF_DIB"); + + hdc = GetDC(hwnd); + if(!hdc) { + DDEMLERROR("DdeStrs.Exe -- ERR:NULL hdc (client)\r\n"); + DdeUnaccessData(hData); //JOHNSP:CHANGE + return 0; + } + + GetClientRect(hwnd,&r); + width=r.right-r.left; + height=r.bottom-r.top; + +#ifdef WIN32 + memcpy(&hmem,lpData,sizeof(HANDLE)); +#else + _fmemcpy(&hmem,lpData,sizeof(HANDLE)); +#endif + + if(!hmem) { + DDEMLERROR("DdeStrs.Exe -- ERR:hmem recieved from server=NULL (client)\r\n"); + DdeUnaccessData(hData); //JOHNSP:CHANGE + ReleaseDC(hwnd,hdc); + return 0; + } + + lp =(LPBYTE)GlobalLock(hmem); + lpbitinfo=(LPBITMAPINFO)lp; + + // iexRGB is ((2^n)-1) where n=biBitCount and we are computing the + // number of RGBQUAD structures. Remember that part of the + // BITMAPINFO structure contains 1 RGBQUAD already. + + iexRGB =((0x0001<<lpbitinfo->bmiHeader.biBitCount)-1)*sizeof(RGBQUAD); + lpbits=lp+(sizeof(BITMAPINFO)+iexRGB); + + SetDIBitsToDevice(hdc, + 0, + 0, + (UINT)lpbitinfo->bmiHeader.biWidth, + (UINT)lpbitinfo->bmiHeader.biHeight, + 0, + 0, + 0, + (UINT)(lpbitinfo->bmiHeader.biHeight), + lpbits, + lpbitinfo, + DIB_RGB_COLORS); + + ReleaseDC(hwnd,hdc); + + DdeUnaccessData(hData); //JOHNSP:CHANGE + + return(TRUE); +} + +BOOL PokeTestItem_BITMAP( +HDDEDATA hData) +{ +HWND hwnd; +HDC hdc,hdcMem; +RECT r; +INT width,height; +HBITMAP hbmap; +HANDLE hobj; +LPBYTE lpData; +DWORD cbData; + + Balance(OFFSET_CLIENT); + + hwnd=(HWND)GetThreadLong(GETCURRENTTHREADID(),OFFSET_HWNDDISPLAY); + SetWindowText(hwnd,"Client - CF_BITMAP"); + + lpData = (LPBYTE) DdeAccessData( hData, &cbData ); + +#ifdef WIN32 + memcpy(&hbmap,lpData,sizeof(HBITMAP)); +#else + _fmemcpy(&hbmap,lpData,sizeof(HBITMAP)); +#endif + + hdc = GetDC(hwnd); + hdcMem = CreateCompatibleDC(hdc); + + if(!hdc||!hdcMem) { + DDEMLERROR("DdeStrs.Exe -- ERR:NULL hdc (client)\r\n"); + DdeUnaccessData(hData); //JOHNSP:CHANGE + if(hdc) ReleaseDC(hwndMain,hdc); + if(hdcMem) DeleteDC(hdcMem); + return 0; + } + + if(!hbmap) { + DDEMLERROR("DdeStrs.Exe -- ERR:NULL hbmap (client)\r\n"); + DdeUnaccessData(hData); //JOHNSP:CHANGE + DeleteDC(hdcMem); + ReleaseDC(hwndMain,hdc); + return 0; + } + + GetClientRect(hwnd,&r); + width=r.right-r.left; + height=r.bottom-r.top; + + hobj=SelectObject(hdcMem,hbmap); + if(!hobj) { + DDEMLERROR("DdeStrs.Exe -- ERR:SelectObject failed (client)\r\n"); + DdeUnaccessData(hData); //JOHNSP:CHANGE + DeleteDC(hdcMem); + ReleaseDC(hwndMain,hdc); + return 0; + } + + if(!BitBlt(hdc,0,0,width,height,hdcMem,0,0,SRCCOPY)) + DDEMLERROR("DdeStrs.Exe -- ERR:BitBlt failed (client)\r\n"); + + hobj=SelectObject(hdcMem,hobj); + DeleteDC(hdcMem); + ReleaseDC(hwnd,hdc); + + DdeUnaccessData(hData); //JOHNSP:CHANGE + + return(TRUE); + +} + +#ifdef WIN32 +BOOL PokeTestItem_ENHMETA( +HDDEDATA hData) +{ +LPBYTE lpData; +HWND hwnd; +HDC hdc; +HANDLE hemf; +DWORD cbData; +RECT r; + + Balance(OFFSET_CLIENT); + + hwnd=(HWND)GetThreadLong(GETCURRENTTHREADID(),OFFSET_HWNDDISPLAY); + SetWindowText(hwnd,"Client - CF_ENHMETAFILE"); + + lpData = (LPBYTE) DdeAccessData( hData, &cbData ); + + hdc = GetDC(hwnd); + if(!hdc) { + DDEMLERROR("DdeStrs.Exe -- ERR:NULL hdc (client)\r\n"); + DdeUnaccessData(hData); //JOHNSP:CHANGE + return 0; + } + +#ifdef WIN32 + memcpy(&hemf,lpData,sizeof(HANDLE)); +#else + _fmemcpy(&hemf,lpData,sizeof(HANDLE)); +#endif + + GetClientRect(hwnd,&r); + if(!PlayEnhMetaFile(hdc,hemf,&r)) + DDEMLERROR("DdeStrs.Exe -- ERR:PlayMetaFile failed (client)\r\n"); + + ReleaseDC(hwnd,hdc); + + DdeUnaccessData(hData); //JOHNSP:CHANGE + + return(TRUE); + +} +#endif + +BOOL PokeTestItem_METAPICT( +HDDEDATA hData) +{ +LPBYTE lpData; +HWND hwnd; +HDC hdc; +HANDLE hmf; +LPMETAFILEPICT lpMfp; +HANDLE hmem; +DWORD cbData; + + Balance(OFFSET_CLIENT); + + hwnd=(HWND)GetThreadLong(GETCURRENTTHREADID(),OFFSET_HWNDDISPLAY); + SetWindowText(hwnd,"Client - CF_METAFILEPICT"); + + lpData = (LPBYTE) DdeAccessData( hData, &cbData ); + + hdc = GetDC(hwnd); + if(!hdc) { + DDEMLERROR("DdeStrs.Exe -- ERR:NULL hdc (client)\r\n"); + DdeUnaccessData(hData); //JOHNSP:CHANGE + return 0; + } + +#ifdef WIN32 + memcpy(&hmem,lpData,sizeof(HANDLE)); +#else + _fmemcpy(&hmem,lpData,sizeof(HANDLE)); +#endif + + lpMfp=(LPMETAFILEPICT)GlobalLock(hmem); + hmf=lpMfp->hMF; + + if(!PlayMetaFile(hdc,hmf)) + DDEMLERROR("DdeStrs.Exe -- ERR:PlayMetaFile failed (client)\r\n"); + + ReleaseDC(hwnd,hdc); + + DdeUnaccessData(hData); //JOHNSP:CHANGE + + return(TRUE); + +} + +BOOL PokeTestItem_PALETTE( +HDDEDATA hData) +{ +LPBYTE lpData; +HWND hwnd; +HPALETTE hpal; +HDC hdc; +RECT r; +HANDLE hobj; +HANDLE hbrush; +DWORD cbData; + + Balance(OFFSET_CLIENT); + + hwnd=(HWND)GetThreadLong(GETCURRENTTHREADID(),OFFSET_HWNDDISPLAY); + SetWindowText(hwnd,"Client - CF_PALETTE"); + + lpData = (LPBYTE) DdeAccessData( hData, &cbData ); + + GetClientRect(hwnd,&r); + + hdc=GetDC(hwnd); + + if(!hdc) { + DDEMLERROR("DdeStrs.Exe -- ERR:NULL hdc (client)\r\n"); + DdeUnaccessData(hData); //JOHNSP:CHANGE + return 0; + } + +#ifdef WIN32 + memcpy(&hpal,lpData,sizeof(HPALETTE)); +#else + _fmemcpy(&hpal,lpData,sizeof(HPALETTE)); +#endif + + hobj=(HPALETTE)SelectPalette(hdc,hpal,FALSE); + + if(!hobj) { + DDEMLERROR("DdeStrs.Exe -- ERR:NULL hobj:SelectPalette failed (client)\r\n"); + DdeUnaccessData(hData); //JOHNSP:CHANGE + ReleaseDC(hwnd,hdc); + return 0; + } + + RealizePalette(hdc); + + hbrush=CreateSolidBrush(PALETTEINDEX(0)); + if(!hbrush) { + DDEMLERROR("DdeStrs.Exe -- ERR:NULL hbrush ret from CreatSolidBrush (client)\r\n"); + DdeUnaccessData(hData); //JOHNSP:CHANGE + SelectPalette(hdc,(HPALETTE)hobj,FALSE); + ReleaseDC(hwnd,hdc); + return 0; + } + + FillRect(hdc,&r,hbrush); + DeleteObject(hbrush); + + SelectPalette(hdc,(HPALETTE)hobj,FALSE); + ReleaseDC(hwnd,hdc); + + DdeUnaccessData(hData); //JOHNSP:CHANGE + + return(TRUE); + +} + +HDDEDATA RenderTestItem_Text( +HDDEDATA hData) +{ +HDC hdc; +HBRUSH hBrush; +PAINTSTRUCT ps; +RECT rc; +HDDEDATA hddedata; +LONG l; +HDDEDATA FAR *hAppOwned; +HANDLE hmem; +HWND hwndDisplay; + + Balance(OFFSET_SERVER); + + hwndDisplay=(HWND)GetThreadLong(GETCURRENTTHREADID(),OFFSET_HWNDDISPLAY); + SetWindowText(hwndDisplay,"Server - CF_TEXT"); + + // if we are running app owned then we just reuse our + // last handle. + + hmem=(HANDLE)GetThreadLong(GETCURRENTTHREADID(),OFFSET_HAPPOWNED); + hAppOwned=(HDDEDATA FAR *)GlobalLock(hmem); + + if(hAppOwned[TXT]!=0L) { + hddedata=hAppOwned[TXT]; + GlobalUnlock(hmem); + return hddedata; + } + + hdc=GetDC(hwndDisplay); + if(!hdc) { + DDEMLERROR("DdeStrs.Exe -- ERR:NULL hdc ret from GetDC! (server)\r\n"); + GlobalUnlock(hmem); + return 0; + } + + hBrush=CreateSolidBrush(WHITE); + if(!hBrush) { + DDEMLERROR("DdeStrs.Exe -- ERR:NULL hBrush ret from CreateSolidBrush! (server)\r\n"); + EndPaint(hwndDisplay,&ps); + GlobalUnlock(hmem); + return 0; + } + + GetClientRect(hwndDisplay,&rc); + FillRect(hdc,&rc,hBrush); + DeleteObject(hBrush); + + DrawText(hdc, "Data:CF_TEXT format", -1, &rc, DT_LEFT|DT_TOP); + ReleaseDC(hwndDisplay,hdc); + + hddedata=DdeAddData(hData, "Data:CF_TEXT format", 20, 0); + + l=GetWindowLong(hwndMain,OFFSET_FLAGS); + if(l&FLAG_APPOWNED) { + hAppOwned[TXT]=hddedata; + } + + GlobalUnlock(hmem); + + return hddedata; +} + +HDDEDATA RenderTestItem_DIB( +HDDEDATA hData) +{ +HWND hwnd; +LONG length; +HDC hdc,hdcMem; +RECT r; +INT width,height,dibhdr; +HBITMAP hbmap; +HANDLE hobj; +LPBITMAPINFO lpbitinfo; +LPBITMAPINFOHEADER lpbithdr; +LPBYTE lpbits; +LPBYTE lpdata; +HDDEDATA hddedata; +INT ip,ibpp; +CHAR sz[100]; +LONG l; +HDDEDATA FAR *hAppOwned; +HANDLE hmem,hm; + + Balance(OFFSET_SERVER); + + hwnd=(HWND)GetThreadLong(GETCURRENTTHREADID(),OFFSET_HWNDDISPLAY); + SetWindowText(hwnd,"Server - CF_DIB"); + + // if we are running app owned then we just reuse our + // last handle. + + hmem=(HANDLE)GetThreadLong(GETCURRENTTHREADID(),OFFSET_HAPPOWNED); + hAppOwned=(HDDEDATA FAR *)GlobalLock(hmem); + + if(hAppOwned[DIB]!=0L) { + hddedata=hAppOwned[DIB]; + GlobalUnlock(hmem); + return hddedata; + } + + length = sizeof(HBITMAP); + + hdc=GetDC(hwnd); + if(!hdc) { + DDEMLERROR("DdeStrs.Exe -- ERR:NULL hdc (server)\r\n"); + GlobalUnlock(hmem); + return 0; + } + + ibpp=GetDeviceCaps(hdc,BITSPIXEL); + ip=GetDeviceCaps(hdc,PLANES); + + hdcMem=CreateCompatibleDC(hdc); + + if(!hdcMem) { + DDEMLERROR("DdeStrs.Exe -- ERR:NULL hdc (server)\r\n"); + ReleaseDC(hwnd,hdc); + GlobalUnlock(hmem); + return 0; + } + + GetClientRect(hwnd,&r); + width=r.right-r.left; + height=r.bottom-r.top; + + hbmap=CreateCompatibleBitmap(hdcMem,width,height); + if(!hbmap) { + DDEMLERROR("DdeStrs.Exe -- ERR:NULL hbmap-CreateCompatibleBitmap failed (server)\r\n"); + DeleteDC(hdcMem); + ReleaseDC(hwnd,hdc); + GlobalUnlock(hmem); + return 0; + } + + hobj=SelectObject(hdcMem,hbmap); + if(!hobj) { + DDEMLERROR("DdeStrs.Exe -- ERR (Server), SelectObject failed\r\n"); + DeleteObject(hbmap); + DeleteDC(hdcMem); + ReleaseDC(hwnd,hdc); + GlobalUnlock(hmem); + return 0; + } + + if(!PatBlt(hdcMem,r.left,r.top,width,height,WHITENESS)) + DDEMLERROR("DdeStrs.Exe -- ERR (Server), PatBlt failed\r\n"); + + // Deselect object (must be done according to docs) + + hobj=SelectObject(hdcMem,hobj); + if(!hobj) DDEMLERROR("DdeStrs.Exe -- ERR (Server), SelectObject [call 2] failed\r\n"); + + + // Set up for a monochrome bitmap. + + dibhdr =sizeof(BITMAPINFO)+(sizeof(RGBQUAD)); + + + // dib header plus area for raw bits + + length =dibhdr+(((width*ibpp)+31)/32)*ip*height*4; + + // Allocate memory for the DIB + + hm=GlobalAlloc(GMEM_ZEROINIT|GMEM_DDESHARE,length); + if(!hm) { + DDEMLERROR("DdeStrs.Exe - RenderTestItem_DIB\r\n"); + wsprintf(sz, "DdeStrs.Exe - GobalAlloc failed, allocation size = %d\r\n", length ); + DDEMLERROR(&sz[0]); + + DeleteObject(hbmap); + DeleteDC(hdcMem); + ReleaseDC(hwnd,hdc); + GlobalUnlock(hmem); + return 0; + } + + lpdata=(LPBYTE)GlobalLock(hm); + + lpbitinfo=(LPBITMAPINFO)lpdata; + lpbithdr=&(lpbitinfo->bmiHeader); + + lpbits=lpdata+dibhdr; + + lpbitinfo->bmiHeader.biSize=sizeof(BITMAPINFOHEADER); + lpbitinfo->bmiHeader.biWidth=width; + lpbitinfo->bmiHeader.biHeight=height; + lpbitinfo->bmiHeader.biPlanes=1; + lpbitinfo->bmiHeader.biBitCount=1; + + // I allocated zero init memory so the other values should + // be 0 and will use the default. + + if(!GetDIBits(hdcMem, + hbmap, + 0, + height, + lpbits, + lpbitinfo, + DIB_RGB_COLORS)) + { + DDEMLERROR("DdeStrs.Exe -- ERR (Server), GetDIBits failed\r\n"); + } + + SetDIBitsToDevice(hdc, + 0, + 0, + (UINT)lpbitinfo->bmiHeader.biWidth, + (UINT)lpbitinfo->bmiHeader.biHeight, + 0, + 0, + 0, + (UINT)(lpbitinfo->bmiHeader.biHeight), + lpbits, + lpbitinfo, + DIB_RGB_COLORS); + + hddedata=DdeAddData(hData, &hm, sizeof(HANDLE), 0); + + GlobalUnlock(hm); + + DeleteObject(hbmap); + + DeleteDC(hdcMem); + ReleaseDC(hwnd,hdc); + + l=GetWindowLong(hwndMain,OFFSET_FLAGS); + if(l&FLAG_APPOWNED) { + hAppOwned[DIB]=hddedata; + } + + GlobalUnlock(hmem); + + return hddedata; +} + +HDDEDATA RenderTestItem_BITMAP( +HDDEDATA hData) +{ +HWND hwnd; +LONG length; +HDC hdc,hdcMem; +RECT r; +INT width,height; +HBITMAP hbmap; +HANDLE hobj; +HDDEDATA hddedata; +DWORD d; +LPBYTE lpdata=(LPBYTE)&d; +LONG l; +HDDEDATA FAR *hAppOwned; +HANDLE hmem; + + Balance(OFFSET_SERVER); + + hwnd=(HWND)GetThreadLong(GETCURRENTTHREADID(),OFFSET_HWNDDISPLAY); + SetWindowText(hwnd,"Server - CF_BITMAP"); + + // if we are running app owned then we just reuse our + // last handle. + + hmem=(HANDLE)GetThreadLong(GETCURRENTTHREADID(),OFFSET_HAPPOWNED); + hAppOwned=(HDDEDATA FAR *)GlobalLock(hmem); + + if(hAppOwned[BITMAP]!=0L) { + hddedata=hAppOwned[BITMAP]; + GlobalUnlock(hmem); + return hddedata; + } + + length = sizeof(HBITMAP); + + hdc=GetDC(hwnd); + hdcMem=CreateCompatibleDC(hdc); + + if(!hdc) { + DDEMLERROR("DdeStrs.Exe -- ERR (Server), NULL hdc\r\n"); + GlobalUnlock(hmem); + return 0; + } + + if(!hdcMem) { + DDEMLERROR("DdeStrs.Exe -- ERR (Server), NULL hdc\r\n"); + ReleaseDC(hwnd,hdc); + GlobalUnlock(hmem); + return 0; + } + + GetClientRect(hwnd,&r); + width=r.right-r.left; + height=r.bottom-r.top; + + hbmap=CreateCompatibleBitmap(hdcMem,width,height); + if(!hbmap) { + DDEMLERROR("DdeStrs.Exe -- ERR (Server), NULL hbmap\r\n"); + DeleteDC(hdcMem); + ReleaseDC(hwnd,hdc); + GlobalUnlock(hmem); + return 0; + } + + hobj=SelectObject(hdcMem,hbmap); + + if(!hobj) { + DDEMLERROR("DdeStrs.Exe -- ERR (Server), SelectObject failed\r\n"); + DeleteObject(hbmap); + DeleteDC(hdcMem); + ReleaseDC(hwnd,hdc); + GlobalUnlock(hmem); + return 0; + } + + if(!PatBlt(hdcMem,r.left,r.top,width,height,WHITENESS)) + DDEMLERROR("DdeStrs.Exe -- ERR (Server), PatBlt failed\r\n"); + + if(!BitBlt(hdc,0,0,width,height,hdcMem,0,0,SRCCOPY)) + DDEMLERROR("DdeStrs.Exe -- ERR (Server), BitBlt failed\r\n"); + +#ifdef WIN32 + memcpy(lpdata,&hbmap,(INT)length); +#else + _fmemcpy(lpdata,&hbmap,(INT)length); +#endif + + hddedata=DdeAddData(hData, lpdata, length, 0); + + // Object will be deleted by client! Not server. + + SelectObject(hdcMem,hobj); + DeleteDC(hdcMem); + ReleaseDC(hwnd,hdc); + + l=GetWindowLong(hwndMain,OFFSET_FLAGS); + if(l&FLAG_APPOWNED) { + hAppOwned[BITMAP]=hddedata; + } + + GlobalUnlock(hmem); + + return hddedata; +} + +#ifdef WIN32 +HDDEDATA RenderTestItem_ENHMETA( +HDDEDATA hData) +{ +HWND hwnd; +HDDEDATA hddedata; +HDC hdc,hdcMem; +INT width,height,length; +RECT r; +HANDLE hemf; +DWORD d; +LPBYTE lpdata=(LPBYTE)&d; +LONG l; +HDDEDATA FAR *hAppOwned; +HANDLE hmem; + +#ifdef WIN32 +XFORM xp; +LPXFORM lpxform=&xp; +#endif + + Balance(OFFSET_SERVER); + + hwnd=GetThreadLong(GETCURRENTTHREADID(),OFFSET_HWNDDISPLAY); + SetWindowText(hwnd,"Server - CF_ENHMETAFILE"); + + // if we are running app owned then we just reuse our + // last handle. + + hmem=(HANDLE)GetThreadLong(GETCURRENTTHREADID(),OFFSET_HAPPOWNED); + hAppOwned=GlobalLock(hmem); + + if(hAppOwned[ENHMETA]!=0L) { + hddedata=hAppOwned[ENHMETA]; + GlobalUnlock(hmem); + return hddedata; + } + + hdc=GetDC(hwnd); //JOHNSP:CHANGE - below few lines + + if(!hdc) { + DDEMLERROR("DdeStrs.Exe -- ERR (Server), NULL hdc\r\n"); + GlobalUnlock(hmem); + return 0; + } + + hdcMem=CreateEnhMetaFile(hdc,NULL,NULL,NULL); + + if(!hdcMem) { + DDEMLERROR("DdeStrs.Exe -- ERR (Server), NULL hdc\r\n"); + ReleaseDC(hwnd,hdc); + GlobalUnlock(hmem); + return 0; + } + + length=sizeof(HANDLE); + + GetClientRect(hwnd,&r); + width=r.right-r.left; + height=r.bottom-r.top; + + if(!PatBlt(hdcMem,r.left,r.top,width,height,WHITENESS)) + DDEMLERROR("DdeStrs.Exe -- ERR:PatBlt failed (server)\r\n"); + + hemf=CloseEnhMetaFile(hdcMem); + if(!hemf) { + DDEMLERROR("DdeStrs.Exe -- ERR:CloseEnhMetaFile failed (server)\r\n"); + ReleaseDC(hwnd,hdc); + GlobalUnlock(hmem); + return 0; + } + +#ifdef WIN32 + memcpy(lpdata,&hemf,length); +#else + _fmemcpy(lpdata,&hemf,length); +#endif + + if(!PlayEnhMetaFile(hdc,hemf,&r)) + DDEMLERROR("DdeStrs.Exe -- ERR:PlayEnhMetaFile failed (server)\r\n"); + + hddedata=DdeAddData(hData, lpdata, length, 0); + + ReleaseDC(hwnd,hdc); + + l=GetWindowLong(hwndMain,OFFSET_FLAGS); + if(l&FLAG_APPOWNED) { + hAppOwned[ENHMETA]=hddedata; + } + + GlobalUnlock(hmem); + + return hddedata; + +} +#endif + +HDDEDATA RenderTestItem_METAPICT( +HDDEDATA hData) +{ +HWND hwnd; +HDDEDATA hddedata; +HDC hdc,hdcMem; +INT width,height,length; +RECT r; +HANDLE hmf; +LPMETAFILEPICT lpMfp; +DWORD d; +LPBYTE lpdata=(LPBYTE)&d; +CHAR sz[100]; +LONG l; +HDDEDATA FAR *hAppOwned; +HANDLE hmem,hm; + + Balance(OFFSET_SERVER); + + hwnd=(HWND)GetThreadLong(GETCURRENTTHREADID(),OFFSET_HWNDDISPLAY); + SetWindowText(hwnd,"Server - CF_METAFILEPICT"); + + // if we are running app owned then we just reuse our + // last handle. + + hmem=(HANDLE)GetThreadLong(GETCURRENTTHREADID(),OFFSET_HAPPOWNED); + hAppOwned=(HDDEDATA FAR *)GlobalLock(hmem); + + if(hAppOwned[METAPICT]!=0L) { + hddedata=hAppOwned[METAPICT]; + GlobalUnlock(hmem); + return hddedata; + } + + hdcMem=CreateMetaFile(NULL); + if(!hdcMem) { + DDEMLERROR("DdeStrs.Exe -- ERR: NULL hdc ret from CreateMetaFile, (Server)\r\n"); + GlobalUnlock(hmem); + return 0; + } + + length=sizeof(HANDLE); + + GetClientRect(hwnd,&r); + width=r.right-r.left; + height=r.bottom-r.top; + + if(!PatBlt(hdcMem,r.left,r.top,width,height,WHITENESS)) + DDEMLERROR("DdeStrs.Exe -- ERR:PatBlt failed (server)\r\n"); + + hmf=CloseMetaFile(hdcMem); + if(!hmf) { + DDEMLERROR("DdeStrs.Exe -- ERR:NULL hmf ret CloseMetaFile! (Server)\r\n"); + GlobalUnlock(hmem); + return 0; + } + + hm=GlobalAlloc(GMEM_ZEROINIT|GMEM_DDESHARE,sizeof(METAFILEPICT)); + if(!hm) { + DDEMLERROR("DdeStrs.Exe - RenderTestItem_METAPICT\r\n"); + wsprintf(sz, "DdeStrs.Exe - GlobalAlloc failed, allocation size = %d\r\n", sizeof(METAFILEPICT) ); + DDEMLERROR(&sz[0]); + DeleteMetaFile(hmf); //JOHNSP:CHANGE + GlobalUnlock(hmem); + return 0; + } + + lpMfp=(LPMETAFILEPICT)GlobalLock(hm); + + lpMfp->mm = MM_TEXT; + lpMfp->xExt = width; + lpMfp->yExt = height; + lpMfp->hMF = hmf; + + GlobalUnlock(hm); + +#ifdef WIN32 + memcpy(lpdata,&hm,length); +#else + _fmemcpy(lpdata,&hm,length); +#endif + + hdc=GetDC(hwnd); + if(!hdc) { + DDEMLERROR("DdeStrs.Exe -- ERR:NULL hdc ret from GetDC, (Server)\r\n"); + GlobalFree(hm); //JOHNSP:CHANGE + DeleteMetaFile(hmf); //JOHNSP:CHANGE + GlobalUnlock(hmem); + return 0; + } + else { + hddedata=DdeAddData(hData, lpdata, length, 0); //JOHNSP:CHANGE + PlayMetaFile(hdc,hmf); + ReleaseDC(hwnd,hdc); + } + + l=GetWindowLong(hwndMain,OFFSET_FLAGS); + if(l&FLAG_APPOWNED) { + hAppOwned[METAPICT]=hddedata; + } + + GlobalUnlock(hmem); + + return hddedata; + +} + +HDDEDATA RenderTestItem_PALETTE( +HDDEDATA hData) +{ +HWND hwnd; +HPALETTE hpal; +LPLOGPALETTE lppal; +HDDEDATA hddedata; +INT length; +DWORD d; +LPBYTE lpdata=(LPBYTE)&d; +CHAR sz[100]; +LONG l; +HDDEDATA FAR *hAppOwned; +HANDLE hmem,hm; + +HDC hdc; +HANDLE hobj; +HANDLE hbrush; +RECT r; + + + Balance(OFFSET_SERVER); + + hwnd=(HWND)GetThreadLong(GETCURRENTTHREADID(),OFFSET_HWNDDISPLAY); + SetWindowText(hwnd,"Server - CF_PALETTE"); + + // if we are running app owned then we just reuse our + // last handle. + + hmem=(HANDLE)GetThreadLong(GETCURRENTTHREADID(),OFFSET_HAPPOWNED); + hAppOwned=(HDDEDATA FAR *)GlobalLock(hmem); + + if(hAppOwned[PALETTE]!=0L) { + hddedata=hAppOwned[PALETTE]; + GlobalUnlock(hmem); + return hddedata; + } + + length=sizeof(LOGPALETTE)+sizeof(PALETTEENTRY); + + lppal=(LPLOGPALETTE)GetMem(length,&hm); + + if(!hm) { + DDEMLERROR("DdeStrs.Exe - RenderTestItem_PALETTE\r\n"); + wsprintf(sz, "DdeStrs.Exe - GlobalAlloc failed, allocation size = %d\r\n", length ); + DDEMLERROR(&sz[0]); + GlobalUnlock(hmem); + return 0; + } + + lppal->palNumEntries=1; + lppal->palVersion=0x0300; + + lppal->palPalEntry[0].peRed =(BYTE)255; + lppal->palPalEntry[0].peGreen=(BYTE)255; + lppal->palPalEntry[0].peBlue =(BYTE)255; + lppal->palPalEntry[0].peFlags=(BYTE)0; + + hpal=CreatePalette(lppal); + if(!hpal) { + DDEMLERROR("DdeStrs.Exe - NULL hpal ret CreatePalette! (server)\r\n"); + FreeMem(hm); + GlobalUnlock(hmem); + return 0; + } + + FreeMem(hm); + +#ifdef WIN32 + memcpy(lpdata,&hpal,sizeof(HANDLE)); +#else + _fmemcpy(lpdata,&hpal,sizeof(HANDLE)); +#endif + + hddedata=DdeAddData(hData, lpdata, sizeof(HPALETTE), 0); + + // Show that palette works. + + // NOTE: From here down if we get a failure we don't abort but + // return hddedata to pass to the client. More basically if + // an error is encountered below it only affects the display + // on the server side! + + GetClientRect(hwnd,&r); + + hdc=GetDC(hwnd); + + if(!hdc) { + DDEMLERROR("DdeStrs.Exe -- ERR:Null hdc (client)\r\n"); + return hddedata; + } + + hobj=(HPALETTE)SelectPalette(hdc,hpal,FALSE); + + if(!hobj) { + DDEMLERROR("DdeStrs.Exe -- ERR:Null hobj:SelectPalette failed (client)\r\n"); + ReleaseDC(hwnd,hdc); + return hddedata; + } + + RealizePalette(hdc); + + hbrush=CreateSolidBrush(PALETTEINDEX(0)); + if(!hbrush) { + DDEMLERROR("DdeStrs.Exe -- ERR:Null hbrush ret from CreatSolidBrush (client)\r\n"); + SelectPalette(hdc,(HPALETTE)hobj,FALSE); + ReleaseDC(hwnd,hdc); + return hddedata; + } + + FillRect(hdc,&r,hbrush); + DeleteObject(hbrush); + + SelectPalette(hdc,(HPALETTE)hobj,FALSE); + ReleaseDC(hwnd,hdc); + + // if we are running appowned, save first created handle + // away for futher use. + + l=GetWindowLong(hwndMain,OFFSET_FLAGS); + if(l&FLAG_APPOWNED) { + hAppOwned[PALETTE]=hddedata; + } + + GlobalUnlock(hmem); + + return hddedata; + +} + +BOOL Execute( +HDDEDATA hData) +{ + LPSTR psz,psz2; + BOOL fRet = FALSE; + LONG cServerhConvs; + int i; + HANDLE hmem; + HCONV FAR *pServerhConvs; + + psz = DdeAccessData(hData, NULL); + +#ifdef WIN16 + if (!_fstricmp(psz, szExecDie)) { +#else + if (!stricmp(psz, szExecDie)) { +#endif + psz2=(LPSTR)-1; + *psz; // GP Fault! + fRet = TRUE; + +#ifdef WIN16 + } else if (!_fstricmp(psz, szExecRefresh)) { +#else + } else if (!stricmp(psz, szExecRefresh)) { +#endif + + if (!DdePostAdvise(GetThreadLong(GETCURRENTTHREADID(),OFFSET_IDINST), 0, 0)) { + DDEMLERROR("DdeStrs.Exe -- ERR DdePostAdvise failed\r\n"); + } + fRet = TRUE; + +#ifdef WIN16 + } else if (!_fstricmp(psz, szExecDisconnect)) { +#else + } else if (!stricmp(psz, szExecDisconnect)) { +#endif + + cServerhConvs=(INT)GetThreadLong(GETCURRENTTHREADID(),OFFSET_CSERVERCONVS); + hmem=(HANDLE)GetThreadLong(GETCURRENTTHREADID(),OFFSET_HSERVERCONVS); + pServerhConvs=(HCONV FAR *)GlobalLock(hmem); + + for (i = 0; i < cServerhConvs; i++) { + if (!DdeDisconnect(pServerhConvs[i])) { + DDEMLERROR("DdeStrs.Exe -- ERR DdeDisconnect failed\r\n"); + } + } + + GlobalUnlock(hmem); + + SetThreadLong(GETCURRENTTHREADID(),OFFSET_CSERVERCONVS,0L); + UpdateCount(hwndMain,OFFSET_SERVER_CONNECT,PNT); + fRet = TRUE; + } + DdeUnaccessData(hData); + return(fRet); +} + +VOID PaintServer( +HWND hwnd, +PAINTSTRUCT *pps) +{ + RECT rc; + static CHAR szT[40]; + + GetClientRect(hwnd, &rc); + + if (fServer) { + rc.left += (rc.right - rc.left) >> 1; // server info is on right half + } + rc.bottom = rc.top + cyText; + + wsprintf(szT, "%d server connections", GetThreadLong(GETCURRENTTHREADID(),OFFSET_CSERVERCONVS)); + DrawText(pps->hdc, szT, -1, &rc, DT_RIGHT); + OffsetRect(&rc, 0, cyText); + + wsprintf(szT, "%d server count", GetWindowLong(hwnd,OFFSET_SERVER)); + DrawText(pps->hdc, szT, -1, &rc, DT_RIGHT); + OffsetRect(&rc, 0, cyText); + +} + + +HDDEDATA FAR PASCAL CustomCallback( +UINT wType, +UINT wFmt, +HCONV hConv, +HSZ hsz1, +HSZ hsz2, +HDDEDATA hData, +DWORD dwData1, +DWORD dwData2) +{ + LONG cServerhConvs,cClienthConvs; + int i; + HANDLE hmem; + HCONV FAR *pServerhConvs; + HCONV hC; + HCONVLIST hConvList=0; + DWORD dwid; + LONG lflags; + + + dwid=GETCURRENTTHREADID(); + cServerhConvs=(INT)GetThreadLong(dwid,OFFSET_CSERVERCONVS); + + switch (wType) { + case XTYP_CONNECT_CONFIRM: + + hmem=(HANDLE)GetThreadLong(dwid,OFFSET_HSERVERCONVS); + pServerhConvs=(HCONV FAR *)GlobalLock(hmem); + + pServerhConvs[cServerhConvs] = hConv; + cServerhConvs++; + SetThreadLong(dwid,OFFSET_CSERVERCONVS,cServerhConvs); + UpdateCount(hwndMain,OFFSET_SERVER_CONNECT,PNT); + if (cServerhConvs >= MAX_SERVER_HCONVS) { + LOGDDEMLERROR("DdeStrs.Exe -- ERR-Number of connections > MAX\r\n"); + cServerhConvs--; + SetThreadLong(dwid,OFFSET_CSERVERCONVS,cServerhConvs); + UpdateCount(hwndMain,OFFSET_SERVER_CONNECT,PNT); + } + GlobalUnlock(hmem); + break; + + case XTYP_DISCONNECT: + + if(fServer) + { + + hmem=(HANDLE)GetThreadLong(dwid,OFFSET_HSERVERCONVS); + pServerhConvs=(HCONV FAR *)GlobalLock(hmem); + + for (i = 0; i < cServerhConvs; i++) + { + + if (pServerhConvs[i] == hConv) + { + cServerhConvs--; + SetThreadLong(dwid,OFFSET_CSERVERCONVS,cServerhConvs); + UpdateCount(hwndMain,OFFSET_SERVER_CONNECT,PNT); + + for (; i < cServerhConvs; i++) + { + pServerhConvs[i] = pServerhConvs[i+1]; + } // for + + break; + + } // if pServerhConvs + + } // for i + + GlobalUnlock(hmem); + + } // fServer + + // If the server is shutting down the conversation then we need + // to change our client connection count. Remember that the + // current conversation is valid until we return from this callback + // so don't count the current conversation. + + if(fClient) + { + + // *** Count Client Connections **** + + cClienthConvs = 0; + hConvList=GetThreadLong(dwid,OFFSET_HCONVLIST); + + if (hConvList) + { + hC = 0; + while (hC = DdeQueryNextServer(hConvList, hC)) + { + if (hC!=hConv) cClienthConvs++; + } // while + + } // if hConvList + + SetThreadLong(dwid,OFFSET_CCLIENTCONVS,cClienthConvs); + + } // if fClient + + InvalidateRect(hwndMain, NULL, TRUE); + + break; + + case XTYP_REGISTER: + case XTYP_UNREGISTER: + lflags=GetWindowLong(hwndMain,OFFSET_FLAGS); + if(fClient && (FLAG_STOP!=(lflags&FLAG_STOP))) + { + ReconnectList(); + } + break; + } + + return(0); +} + +BOOL Balance( INT itype ) { + + if(itype==OFFSET_SERVER) { + UpdateCount(hwndMain,OFFSET_SERVER,INC); + } + else { + UpdateCount(hwndMain,OFFSET_CLIENT,INC); + } + + return TRUE; + +} + diff --git a/private/mvdm/wow16/ddeml/tests/ddestrs/sources b/private/mvdm/wow16/ddeml/tests/ddestrs/sources new file mode 100644 index 000000000..03153145f --- /dev/null +++ b/private/mvdm/wow16/ddeml/tests/ddestrs/sources @@ -0,0 +1,24 @@ +MAJORCOMP=test +MINORCOMP=ddestrs + +TARGETNAME=ddestrs +TARGETPATH=obj +TARGETTYPE=LIBRARY +TARGETLIBS= + +INCLUDES=. + +SOURCES=ddestrs.c ddestrs.rc client.c server.c globals.c wrapper.c cmdln.c + +C_DEFINES=-DWIN32 + +!if 0 +NTDEBUG=ntsd +NTDEBUGTYPE=windbg +386_OPTIMIZATION=/Od +!endif + +UMTYPE=windows +UMAPPL=ddestrs +UMENTRY=winmain +UMLIBS=obj\*\ddestrs.lib obj\*\ddestrs.res diff --git a/private/mvdm/wow16/ddeml/tests/ddestrs/wrapper.c b/private/mvdm/wow16/ddeml/tests/ddestrs/wrapper.c new file mode 100644 index 000000000..f477f76cf --- /dev/null +++ b/private/mvdm/wow16/ddeml/tests/ddestrs/wrapper.c @@ -0,0 +1,793 @@ +/***************************************************************************\ + + PROGRAM : wrapper.c + + PURPOSE : This is not a full program but a module you can include + in your code. It implements a standard DDEML callback + function that allows you to have most of your DDE table + driven. The default callback function handles all basic + System Topic information based on the tables you give + to this app. + + LIMITATIONS : This only supports servers that: + have only one service name + have enumerable topics and items + do not change the topics or items they support over time. + + + EXPORTED ROUTINES: + + InitializeDDE() + Use this to initialize the callback function tables and the DDEML + + UninitializeDDE() + Use this to cleanup this module and uninitialize the DDEML instance. + +\***************************************************************************/ + +#include <windows.h> +#include <ddeml.h> +#include <string.h> +#include "wrapper.h" +#include <port1632.h> +#include "ddestrs.h" + +extern BOOL fServer; +extern LPSTR pszNetName; +extern LONG SetThreadLong(DWORD,INT,LONG); +extern LONG GetThreadLong(DWORD,INT); +extern LPSTR TStrCpy( LPSTR, LPSTR); + +BOOL InExit(VOID); +VOID InitHszs(LPDDESERVICETBL psi); +UINT GetFormat(LPSTR pszFormat); +VOID FreeHszs(LPDDESERVICETBL psi); +HDDEDATA APIENTRY WrapperCallback(UINT wType, UINT wFmt, HCONV hConv, HSZ hsz1, + HSZ hsz2, HDDEDATA hData, DWORD dwData1, DWORD dwData2); + +BOOL DoCallback(HCONV,HSZ,HSZ,UINT,UINT,HDDEDATA,LPDDESERVICETBL,HDDEDATA *); + +HDDEDATA ReqItems(HDDEDATA hDataOut, LPDDETOPICTBL ptpc); +HDDEDATA AddReqFormat(HDDEDATA hDataOut, LPSTR pszFmt); +HDDEDATA ReqFormats(HDDEDATA hDataOut, LPDDETOPICTBL ptpc); +HDDEDATA DoWildConnect(HSZ hszTopic); + +PFNCALLBACK lpfnUserCallback = NULL; +PFNCALLBACK lpfnWrapperCallback = NULL; + +LPDDESERVICETBL pasi = NULL; +char tab[] = "\t"; + +#define FOR_EACH_TOPIC(psvc, ptpc, i) for (i = 0, ptpc=(psvc)->topic; i < (int)(psvc)->cTopics; i++, ptpc++) +#define FOR_EACH_ITEM(ptpc, pitm, i) for (i = 0, pitm=(ptpc)->item; i < (int)(ptpc)->cItems; i++, pitm++) +#define FOR_EACH_FORMAT(pitm, pfmt, i) for (i = 0, pfmt=(pitm)->fmt; i < (int)(pitm)->cFormats;i++, pfmt++) + + + +/* STANDARD PREDEFINED FORMATS */ + +#ifdef WIN32 +#define CSTDFMTS 14 +#else +#define CSTDFMTS 12 +#endif + +struct { + UINT wFmt; + PSTR pszFmt; +} StdFmts[CSTDFMTS] = { + { CF_TEXT , "TEXT" } , + { CF_BITMAP , "BITMAP" } , + { CF_METAFILEPICT, "METAFILEPICT" } , + { CF_SYLK , "SYLK" } , + { CF_DIF , "DIF" } , + { CF_TIFF , "TIFF" } , + { CF_OEMTEXT , "OEMTEXT" } , + { CF_DIB , "DIB" } , + { CF_PALETTE , "PALETTE" } , + { CF_PENDATA , "PENDATA" } , + { CF_RIFF , "RIFF" } , + { CF_WAVE , "WAVE" } , +#ifdef WIN32 + { CF_UNICODETEXT , "UNICODETEXT" } , + { CF_ENHMETAFILE , "ENHMETAFILE" } , +#endif +}; + + + +HDDEDATA SysReqTopics(HDDEDATA hDataOut); +HDDEDATA SysReqSysItems(HDDEDATA hDataOut); +HDDEDATA SysReqFormats(HDDEDATA hDataOut); + + /* STANDARD SERVICE INFO TABLES */ + +DDEFORMATTBL StdSvcSystopicTopicsFormats[] = { + "TEXT", 0, 0, NULL, SysReqTopics +}; + +DDEFORMATTBL StdSvcSystopicSysitemsFormats[] = { + "TEXT", 0, 0, NULL, SysReqSysItems +}; + +DDEFORMATTBL StdSvcSystopicFormatsFormats[] = { + "TEXT", 0, 0, NULL, SysReqFormats +}; + +#define ITPC_TOPICS 0 +#define ITPC_SYSITEMS 1 +#define ITPC_FORMATS 2 +#define ITPC_ITEMLIST 3 + +#define ITPC_COUNT 4 + +DDEITEMTBL StdSvcSystopicItems[] = { + { SZDDESYS_ITEM_TOPICS, 0, 1, 0, StdSvcSystopicTopicsFormats }, + { SZDDESYS_ITEM_SYSITEMS, 0, 1, 0, StdSvcSystopicSysitemsFormats }, + { SZDDESYS_ITEM_FORMATS, 0, 1, 0, StdSvcSystopicFormatsFormats }, + { SZDDE_ITEM_ITEMLIST, 0, 1, 0, StdSvcSystopicSysitemsFormats }, +}; + +DDETOPICTBL StdSvc[] = { + SZDDESYS_TOPIC, 0, ITPC_COUNT, 0, StdSvcSystopicItems +}; + +DDESERVICETBL SSI = { + NULL, 0, 1, 0, StdSvc +}; + +/*********************************************************************/ + + +BOOL InitializeDDE( +PFNCALLBACK lpfnCustomCallback, +LPDWORD pidInst, +LPDDESERVICETBL AppSvcInfo, +DWORD dwFilterFlags, +HANDLE hInst) +{ +DWORD idI=0; + + if (lpfnCustomCallback) { + lpfnUserCallback = (PFNCALLBACK)MakeProcInstance((FARPROC)lpfnCustomCallback, hInst); + } + lpfnWrapperCallback = (PFNCALLBACK)MakeProcInstance((FARPROC)WrapperCallback, hInst); + + if (DdeInitialize(&idI, lpfnWrapperCallback, dwFilterFlags, 0)) { + SetThreadLong(GETCURRENTTHREADID(),OFFSET_IDINST,idI); + if (lpfnCustomCallback) { + FreeProcInstance((FARPROC)lpfnUserCallback); + } + FreeProcInstance((FARPROC)lpfnWrapperCallback); + return(FALSE); + } + else SetThreadLong(GETCURRENTTHREADID(),OFFSET_IDINST,idI); + *pidInst = idI; + InitHszs(AppSvcInfo); + InitHszs(&SSI); + pasi = AppSvcInfo; + + if (fServer) { + DdeNameService(idI, pasi->hszService, 0, DNS_REGISTER); + } + + return(TRUE); +} + + + +VOID InitHszs( +LPDDESERVICETBL psi) +{ + int iTopic, iItem, iFmt; + LPDDETOPICTBL ptpc; + LPDDEITEMTBL pitm; + LPDDEFORMATTBL pfmt; + DWORD idI; + CHAR sz[120]; + LPBYTE psz; + LPBYTE pNet; + + pNet=pszNetName; + + idI=GetThreadLong(GETCURRENTTHREADID(),OFFSET_IDINST); + + if (psi->pszService) { + + // This area of code inplements the clients ability + // to see net drives. This is the -n option. + + if(pNet) + { + + sz[0]='\\'; + sz[1]='\\'; + psz=&sz[2]; + + psz=TStrCpy(psz,pNet); + + while(*++psz!='\0'); + + *psz++='\\'; + + psz=TStrCpy(psz,psi->pszService); + psz=&sz[0]; + + psi->hszService = DdeCreateStringHandle(idI, psz, 0); + + } // pNet + + else psi->hszService = DdeCreateStringHandle(idI, psi->pszService, 0); + } + FOR_EACH_TOPIC(psi, ptpc, iTopic) { + ptpc->hszTopic = DdeCreateStringHandle(idI, ptpc->pszTopic, 0); + FOR_EACH_ITEM(ptpc, pitm, iItem) { + pitm->hszItem = DdeCreateStringHandle(idI, pitm->pszItem, 0); + FOR_EACH_FORMAT(pitm, pfmt, iFmt) { + pfmt->wFmt = GetFormat(pfmt->pszFormat); + } + } + } +} + + +/* + * This function allows apps to use standard CF_ formats. The string + * given may be in the StdFmts[] table. + */ + +UINT GetFormat( +LPSTR pszFormat) +{ + int iFmt; + + for (iFmt = 0; iFmt < CSTDFMTS; iFmt++) { + if (!lstrcmp(pszFormat, StdFmts[iFmt].pszFmt)) { + return(StdFmts[iFmt].wFmt); + } + } + return(RegisterClipboardFormat(pszFormat)); +} + + + +VOID UninitializeDDE() +{ +DWORD idI; + + if (pasi == NULL) { + return; + } + + idI=GetThreadLong(GETCURRENTTHREADID(),OFFSET_IDINST); + + DdeNameService(idI, pasi->hszService, 0, DNS_UNREGISTER); + FreeHszs(pasi); + FreeHszs(&SSI); + DdeUninitialize(idI); + if (lpfnUserCallback) { + FreeProcInstance((FARPROC)lpfnUserCallback); + } + FreeProcInstance((FARPROC)lpfnWrapperCallback); +} + + + +VOID FreeHszs( +LPDDESERVICETBL psi) +{ + int iTopic, iItem; + LPDDETOPICTBL ptpc; + LPDDEITEMTBL pitm; + DWORD idI; + + idI=GetThreadLong(GETCURRENTTHREADID(),OFFSET_IDINST); + + DdeFreeStringHandle(idI, psi->hszService); + FOR_EACH_TOPIC(psi, ptpc, iTopic) { + DdeFreeStringHandle(idI, ptpc->hszTopic); + FOR_EACH_ITEM(ptpc, pitm, iItem) { + DdeFreeStringHandle(idI, pitm->hszItem); + } + } +} + +BOOL InExit( VOID ) { +LONG l; + + if(!IsWindow((HWND)GetThreadLong(GETCURRENTTHREADID(),OFFSET_HWNDDISPLAY))) { + DDEMLERROR("DdeStrs.Exe -- INF:Invalid hwndDisplay, returning NAck!\r\n"); + return TRUE; + } + + if(!IsWindow(hwndMain)) { + DDEMLERROR("DdeStrs.Exe -- INF:Invalid hwndMain, returning NAck!\r\n"); + return TRUE; + } + + // No need for error message on this one. This is expected to happen + // when queues fill up under extreme conditions. + + l=GetWindowLong(hwndMain,OFFSET_FLAGS); + if(l&FLAG_STOP) { + return TRUE; + } + + return FALSE; + +} + +HDDEDATA APIENTRY WrapperCallback( +UINT wType, +UINT wFmt, +HCONV hConv, +HSZ hsz1, +HSZ hsz2, +HDDEDATA hData, +DWORD dwData1, +DWORD dwData2) +{ + HDDEDATA hDataRet; + + switch (wType) { + case XTYP_WILDCONNECT: + if (!hsz2 || !DdeCmpStringHandles(hsz2, pasi->hszService)) { + return(DoWildConnect(hsz1)); + } + break; + + case XTYP_CONNECT: + + if(!fServer) { + DDEMLERROR("DdeStrs.Exe -- Recieved XTYP_CONNECT when client!\r\n"); + } + + case XTYP_ADVSTART: + case XTYP_EXECUTE: + case XTYP_REQUEST: + case XTYP_ADVREQ: + case XTYP_ADVDATA: + case XTYP_POKE: + + if(InExit()) return(0); + + if(DoCallback(hConv, hsz1, hsz2, wFmt, wType, hData, + &SSI, &hDataRet)) + return(hDataRet); + + if (DoCallback(hConv, hsz1, hsz2, wFmt, wType, hData, + pasi, &hDataRet)) + return(hDataRet); + + /* Fall Through */ + default: + if (lpfnUserCallback != NULL) { + return(lpfnUserCallback(wType, wFmt, hConv, hsz1, hsz2, hData, + dwData1, dwData2)); + } + } + return(0); +} + + + + +BOOL DoCallback( +HCONV hConv, +HSZ hszTopic, +HSZ hszItem, +UINT wFmt, +UINT wType, +HDDEDATA hDataIn, +LPDDESERVICETBL psi, +HDDEDATA *phDataRet) +{ + int iTopic, iItem, iFmt; + LPDDEFORMATTBL pfmt; + LPDDEITEMTBL pitm; + LPDDETOPICTBL ptpc; +#ifdef WIN32 + CONVINFO ci; +#endif + LONG l; + BOOL fCreate=FALSE; + HANDLE hmem; + HDDEDATA FAR *hAppOwned; + + FOR_EACH_TOPIC(psi, ptpc, iTopic) { + if (DdeCmpStringHandles(ptpc->hszTopic, hszTopic)) + continue; + + if (wType == XTYP_EXECUTE) { + if (ptpc->lpfnExecute) { + if ((*ptpc->lpfnExecute)(hDataIn)) + *phDataRet = (HDDEDATA)DDE_FACK; + } else { + *phDataRet = (HDDEDATA)DDE_FNOTPROCESSED; + } + return(TRUE); + } + + if (wType == XTYP_CONNECT) { + *phDataRet = (HDDEDATA)TRUE; + return(TRUE); + } + + FOR_EACH_ITEM(ptpc, pitm, iItem) { + if (DdeCmpStringHandles(pitm->hszItem, hszItem)) + continue; + + FOR_EACH_FORMAT(pitm, pfmt, iFmt) { + if (pfmt->wFmt != wFmt) + continue; + + switch (wType) { + case XTYP_ADVSTART: + *phDataRet = (HDDEDATA)TRUE; + break; + +// XTYP_POKE CHANGE +#if 0 + case XTYP_POKE: +#endif + + case XTYP_ADVDATA: + if (pfmt->lpfnPoke) { + if ((*pfmt->lpfnPoke)(hDataIn)) + { + *phDataRet = (HDDEDATA)DDE_FACK; + break; + } + } else { + *phDataRet = (HDDEDATA)DDE_FNOTPROCESSED; + } + break; + +// XTYP_POKE CHANGE +#ifdef WIN32 // TURNED BACK ON + case XTYP_POKE: + *phDataRet = (HDDEDATA)DDE_FACK; + ci.cb = sizeof(CONVINFO); + + if (DdeQueryConvInfo(hConv, QID_SYNC, &ci)) + { + if (!(ci.wStatus & ST_ISSELF)) { + DdePostAdvise(GetThreadLong(GETCURRENTTHREADID(),OFFSET_IDINST), hszTopic, hszItem); + } + } + else + { + *phDataRet = (HDDEDATA)DDE_FNOTPROCESSED; + } + break; +#endif + + + case XTYP_REQUEST: + case XTYP_ADVREQ: + if (pfmt->lpfnRequest) { + HDDEDATA hDataOut; + + l=GetWindowLong(hwndMain,OFFSET_FLAGS); + if(l&FLAG_APPOWNED) { + + hmem=(HANDLE)GetThreadLong(GETCURRENTTHREADID(),OFFSET_HAPPOWNED); + hAppOwned=(HDDEDATA FAR *)GlobalLock(hmem); + + switch (pfmt->wFmt) { + case CF_TEXT: if(hAppOwned[TXT]==0L) fCreate=TRUE; + break; + case CF_DIB: if(hAppOwned[DIB]==0L) fCreate=TRUE; + break; + case CF_BITMAP: if(hAppOwned[BITMAP]==0L) fCreate=TRUE; + break; +#ifdef WIN32 + case CF_ENHMETAFILE: if(hAppOwned[ENHMETA]==0L) fCreate=TRUE; + break; +#endif + case CF_METAFILEPICT: if(hAppOwned[METAPICT]==0L) fCreate=TRUE; + break; + case CF_PALETTE: if(hAppOwned[PALETTE]==0L) fCreate=TRUE; + break; + default: + DDEMLERROR("DdeStrs.Exe -- ERR: Unexpected switch constant in DoCallback!\r\n"); + break; + + } // switch + + GlobalUnlock(hmem); + + if (fCreate) { + hDataOut = DdeCreateDataHandle( GetThreadLong(GETCURRENTTHREADID(),OFFSET_IDINST), + NULL, + 0, + 0, + pitm->hszItem, + pfmt->wFmt, + HDATA_APPOWNED); + } // fCreate + + } // l&FLAG_APPOWNED + else { + hDataOut = DdeCreateDataHandle( GetThreadLong(GETCURRENTTHREADID(),OFFSET_IDINST), + NULL, + 0, + 0, + pitm->hszItem, + pfmt->wFmt, + 0); + } // else l&FLAG_APPOWNED + + *phDataRet = (HDDEDATA)(*pfmt->lpfnRequest)(hDataOut); + if (!*phDataRet) { + DdeFreeDataHandle(hDataOut); + } + } else { + *phDataRet = 0; + } + break; + } + return(TRUE); + } + } + + /* item not found in tables */ + + if (wFmt == CF_TEXT && (wType == XTYP_REQUEST || wType == XTYP_ADVREQ)) { + /* + * If formats item was requested and not found in the tables, + * return a list of formats supported under this topic. + */ + if (!DdeCmpStringHandles(hszItem, SSI.topic[0].item[ITPC_FORMATS].hszItem)) { + *phDataRet = DdeCreateDataHandle(GetThreadLong(GETCURRENTTHREADID(),OFFSET_IDINST), + NULL, + 0, + 0, + hszItem, + wFmt, + 0); + *phDataRet = ReqFormats(*phDataRet, ptpc); + return(TRUE); + } + /* + * If sysitems or topicitemlist item was requested and not found, + * return a list of items supported under this topic. + */ + if (!DdeCmpStringHandles(hszItem, SSI.topic[0].item[ITPC_SYSITEMS].hszItem) || + !DdeCmpStringHandles(hszItem, SSI.topic[0].item[ITPC_ITEMLIST].hszItem)) { + *phDataRet = ReqItems(DdeCreateDataHandle(GetThreadLong(GETCURRENTTHREADID(),OFFSET_IDINST), + NULL, + 0, + 0, + hszItem, + wFmt, + 0), + ptpc); + return(TRUE); + } + } + } + + /* no topics fit */ + + return(FALSE); +} + + +/* + * These are Request routines for supporting the system topic. + * Their behavior depends on the table contents. + */ + +HDDEDATA SysReqTopics( +HDDEDATA hDataOut) // data handle to add output data to. +{ + int iTopic, cb, cbOff; + LPDDETOPICTBL ptpc; + + /* + * This code assumes SSI only contains the system topic. + */ + + cbOff = 0; + FOR_EACH_TOPIC(pasi, ptpc, iTopic) { + if (!DdeCmpStringHandles(ptpc->hszTopic, SSI.topic[0].hszTopic)) { + continue; // don't add systopic twice. + } + cb = lstrlen(ptpc->pszTopic); + hDataOut = DdeAddData(hDataOut, ptpc->pszTopic, (DWORD)cb, (DWORD)cbOff); + cbOff += cb; + hDataOut = DdeAddData(hDataOut, (LPBYTE)&tab, (DWORD)1, (DWORD)cbOff); + cbOff++; + } + + hDataOut = DdeAddData(hDataOut, SSI.topic[0].pszTopic, + (DWORD)lstrlen(SSI.topic[0].pszTopic) + 1, (DWORD)cbOff); + + return(hDataOut); +} + + + +HDDEDATA SysReqSysItems( +HDDEDATA hDataOut) +{ + return(ReqItems(hDataOut, &SSI.topic[ITPC_SYSITEMS])); +} + + +/* + * Given a topic table, this function returns a tab delimited list of + * items supported under that topic. + */ +HDDEDATA ReqItems( +HDDEDATA hDataOut, +LPDDETOPICTBL ptpc) +{ + int cb, iItem, cbOff = 0; + LPDDEITEMTBL pitm; + + /* + * return a list of all the items within this topic + */ + FOR_EACH_ITEM(ptpc, pitm, iItem) { + cb = lstrlen(pitm->pszItem); + hDataOut = DdeAddData(hDataOut, pitm->pszItem, (DWORD)cb, (DWORD)cbOff); + cbOff += cb; + hDataOut = DdeAddData(hDataOut, (LPBYTE)&tab, (DWORD)1, (DWORD)cbOff); + cbOff++; + } + + + /* + * if this is for the System Topic, add to the list our default items. + */ + + if (!DdeCmpStringHandles(ptpc->hszTopic, SSI.topic[0].hszTopic)) { + ptpc = &SSI.topic[0]; + FOR_EACH_ITEM(ptpc, pitm, iItem) { + cb = lstrlen(pitm->pszItem); + hDataOut = DdeAddData(hDataOut, pitm->pszItem, (DWORD)cb, (DWORD)cbOff); + cbOff += cb; + hDataOut = DdeAddData(hDataOut, (LPBYTE)&tab, (DWORD)1, (DWORD)cbOff); + cbOff++; + } + } else { + /* + * Add the standard TopicListItems and SysItem items. + */ + cb = lstrlen(SSI.topic[0].item[ITPC_SYSITEMS].pszItem); + hDataOut = DdeAddData(hDataOut, + SSI.topic[0].item[ITPC_SYSITEMS].pszItem, (DWORD)cb, (DWORD)cbOff); + cbOff += cb; + hDataOut = DdeAddData(hDataOut, (LPBYTE)&tab, (DWORD)1, (DWORD)cbOff); + cbOff++; + + cb = lstrlen(SSI.topic[0].item[ITPC_ITEMLIST].pszItem); + hDataOut = DdeAddData(hDataOut, + SSI.topic[0].item[ITPC_ITEMLIST].pszItem, (DWORD)cb, (DWORD)cbOff); + cbOff += cb; + hDataOut = DdeAddData(hDataOut, (LPBYTE)&tab, (DWORD)1, (DWORD)cbOff); + cbOff++; + + cb = lstrlen(SSI.topic[0].item[ITPC_FORMATS].pszItem); + hDataOut = DdeAddData(hDataOut, + SSI.topic[0].item[ITPC_FORMATS].pszItem, (DWORD)cb, (DWORD)cbOff); + cbOff += cb; + hDataOut = DdeAddData(hDataOut, (LPBYTE)&tab, (DWORD)1, (DWORD)cbOff); + cbOff++; + } + + hDataOut = DdeAddData(hDataOut, '\0', (DWORD)1, (DWORD)--cbOff); + return(hDataOut); +} + + + + +HDDEDATA SysReqFormats( +HDDEDATA hDataOut) +{ + int iTopic, iItem, iFmt; + LPDDETOPICTBL ptpc; + LPDDEITEMTBL pitm; + LPDDEFORMATTBL pfmt; + + hDataOut = DdeAddData(hDataOut, (LPBYTE)"TEXT", 5, 0); + FOR_EACH_TOPIC(pasi, ptpc, iTopic) { + FOR_EACH_ITEM(ptpc, pitm, iItem) { + FOR_EACH_FORMAT(pitm, pfmt, iFmt) { + hDataOut = AddReqFormat(hDataOut, pfmt->pszFormat); + } + } + } + return(hDataOut); +} + + + +HDDEDATA AddReqFormat( +HDDEDATA hDataOut, +LPSTR pszFmt) +{ + LPSTR pszList; + DWORD cbOff; + + pszList = DdeAccessData(hDataOut, NULL); + +#if WIN16 + if (_fstrstr(pszList, pszFmt) == NULL) { +#else + if (strstr(pszList, pszFmt) == NULL) { +#endif + cbOff = lstrlen(pszList); + DdeUnaccessData(hDataOut); + hDataOut = DdeAddData(hDataOut, (LPBYTE)&tab, 1, cbOff++); + hDataOut = DdeAddData(hDataOut, (LPBYTE)pszFmt, lstrlen(pszFmt) + 1, cbOff); + } else { + DdeUnaccessData(hDataOut); + } + + return(hDataOut); +} + + +HDDEDATA ReqFormats( +HDDEDATA hDataOut, +LPDDETOPICTBL ptpc) +{ + int iItem, iFmt; + LPDDEITEMTBL pitm; + LPDDEFORMATTBL pfmt; + + hDataOut = DdeAddData(hDataOut, "", 1, 0); + FOR_EACH_ITEM(ptpc, pitm, iItem) { + FOR_EACH_FORMAT(pitm, pfmt, iFmt) { + hDataOut = AddReqFormat(hDataOut, pfmt->pszFormat); + } + } + return(hDataOut); +} + + + +HDDEDATA DoWildConnect( +HSZ hszTopic) +{ + LPDDETOPICTBL ptpc; + HDDEDATA hData; + PHSZPAIR pHszPair; + int iTopic, cTopics = 2; + + if (!hszTopic) { + cTopics += pasi->cTopics; + } + + hData = DdeCreateDataHandle(GetThreadLong(GETCURRENTTHREADID(),OFFSET_IDINST), + NULL, + cTopics * sizeof(HSZPAIR), + 0, + 0, + 0, + 0); + pHszPair = (HSZPAIR FAR *)DdeAccessData(hData, NULL); + pHszPair->hszSvc = pasi->hszService; + pHszPair->hszTopic = SSI.topic[0].hszTopic; // always support systopic. + pHszPair++; + ptpc = &pasi->topic[0]; + FOR_EACH_TOPIC(pasi, ptpc, iTopic) { + if (hszTopic && DdeCmpStringHandles(hszTopic, ptpc->hszTopic)) { + continue; + } + if (!DdeCmpStringHandles(ptpc->hszTopic, SSI.topic[0].hszTopic)) { + continue; // don't enter systopic twice. + } + pHszPair->hszSvc = pasi->hszService; + pHszPair->hszTopic = ptpc->hszTopic; + pHszPair++; + } + pHszPair->hszSvc = 0; + pHszPair->hszTopic = 0; + DdeUnaccessData(hData); + return(hData); +} diff --git a/private/mvdm/wow16/ddeml/tests/ddestrs/wrapper.h b/private/mvdm/wow16/ddeml/tests/ddestrs/wrapper.h new file mode 100644 index 000000000..5cfbc261b --- /dev/null +++ b/private/mvdm/wow16/ddeml/tests/ddestrs/wrapper.h @@ -0,0 +1,80 @@ +/***************************************************************************\ + + MODULE : wrapper.h + + PURPOSE : This is not a full program but a module you can include + in your code. It implements a standard DDEML callback + function that allows you to have most of your DDE table + driven. The default callback function handles all basic + System Topic information based on the tables you give + to this app. + + LIMITATIONS : This only supports servers that: + have only one service name + have enumerable topics and items + do not change the topics or items they support over time. + +\***************************************************************************/ + + +/* TYPES */ + +typedef BOOL (*CBFNIN)(HDDEDATA); +typedef HDDEDATA (*CBFNOUT)(HDDEDATA); + + + +/* STRUCTURES */ + +typedef struct _DDEFORMATTBL { + LPSTR pszFormat; + UINT wFmt; + UINT wFmtFlags; + CBFNIN lpfnPoke; + CBFNOUT lpfnRequest; +} DDEFORMATTBL; +typedef DDEFORMATTBL *PDDEFORMATTBL; +typedef DDEFORMATTBL FAR *LPDDEFORMATTBL; + +typedef struct _DDEITEMTBL { + LPSTR pszItem; + HSZ hszItem; + UINT cFormats; + UINT wItemFlags; + LPDDEFORMATTBL fmt; +} DDEITEMTBL; +typedef DDEITEMTBL *PDDEITEMTBL; +typedef DDEITEMTBL FAR *LPDDEITEMTBL; + + +typedef struct _DDETOPICTBL { + LPSTR pszTopic; + HSZ hszTopic; + UINT cItems; + UINT wTopicFlags; + LPDDEITEMTBL item; + CBFNIN lpfnExecute; +} DDETOPICTBL; +typedef DDETOPICTBL *PDDETOPICTBL; +typedef DDETOPICTBL FAR *LPDDETOPICTBL; + +typedef struct _DDESERVICETBL { + LPSTR pszService; + HSZ hszService; + UINT cTopics; + UINT wServiceFlags; + LPDDETOPICTBL topic; +} DDESERVICETBL; +typedef DDESERVICETBL *PDDESERVICETBL; +typedef DDESERVICETBL FAR *LPDDESERVICETBL; + + + +/* PROTOTYPES */ + +BOOL InitializeDDE(PFNCALLBACK lpfnCustomCallback, LPDWORD pidInst, + LPDDESERVICETBL AppSvcInfo, DWORD dwFilterFlags, HANDLE hInst); + +VOID UninitializeDDE(VOID); + + |