static trap_retval DoRemotePut( byte *snd, trap_elen len ) { WORD rc; putstring( "RemotePut\r\n" ); putconnstatus( Connection ); if( len == 0 ) { _INITSPXECB( Send, 1, NULL, 0 ); } else { _INITSPXECB( Send, 2, (char *)snd, len ); } SendECB.hsem = (HSEM) &SendSem; SendHead.connectionCtl |= 0x10; SendHead.packetLen = _SWAPINT( sizeof( SendHead ) + len ); DosSemSet( &SendSem ); rc = SpxSendSequencedPacket( Connection, &SendECB ); putrc( "SPXSendSequencedPacket", rc ); for( ;; ) { /* I don't know what the 0x1001 status is - I can't find it in any documentation, but if we don't wait for it to clear, things mess up badly. */ if( SendECB.status != SPX_SUCCESSFUL && !InUse( SendECB ) && SendECB.status != 0x1001 ) break; rc = DosSemWait( &SendSem, 1000 ); if( rc != ERROR_SEM_TIMEOUT ) { break; } } SendECB.hsem = 0; putstring( "Done RemotePut\r\n" ); return( len ); }
static bool InitServer( void ) { TID tid; DosSemSet( &BroadCastStop ); DosSemSet( &BroadCastStart ); DosCreateThread( Broadcast, &tid, BroadcastStack + STACKSIZE ); DosSemWait( &BroadCastStart, -1L ); DosCreateThread( Respond, &tid, RespondStack + STACKSIZE ); return( TRUE ); }
unsigned OnAnotherThreadSimpAccess( unsigned in_len, in_data_p in_data, unsigned out_len, out_data_p out_data ) { unsigned result; if( !ToldWinHandle || IsTrapFilePumpingMessageQueue() ) { return( TrapSimpAccess( in_len, in_data, out_len, out_data ) ); } else { DosSemClear( &PumpMessageSem ); result = TrapSimpAccess( in_len, in_data, out_len, out_data ); WinPostMsg( GUIGetSysHandle( WndGui( WndMain ) ), WM_QUIT, 0, 0 ); DosSemWait( &PumpMessageDoneSem, SEM_INDEFINITE_WAIT ); DosSemSet( &PumpMessageDoneSem ); return( result ); } }
unsigned OnAnotherThreadAccess( trap_elen in_num, in_mx_entry_p in_mx, trap_elen out_num, mx_entry_p out_mx ) { unsigned result; if( !ToldWinHandle || IsTrapFilePumpingMessageQueue() ) { return( TrapAccess( in_num, in_mx, out_num, out_mx ) ); } else { DosSemClear( &PumpMessageSem ); result = TrapAccess( in_num, in_mx, out_num, out_mx ); WinPostMsg( GUIGetSysHandle( WndGui( WndMain ) ), WM_QUIT, 0, 0 ); DosSemWait( &PumpMessageDoneSem, SEM_INDEFINITE_WAIT ); DosSemSet( &PumpMessageDoneSem ); return( result ); } }
unsigned OnAnotherThread( unsigned(*rtn)(unsigned,void *,unsigned,void *), unsigned in_len, void *in, unsigned out_len, void *out ) { unsigned result; if( !ToldWinHandle || IsTrapFilePumpingMessageQueue() ) { return( rtn( in_len, in, out_len, out ) ); } else { DosSemClear( &PumpMessageSem ); result = rtn( in_len, in, out_len, out ); WinPostMsg( GUIGetSysHandle( WndGui( WndMain ) ), WM_QUIT, 0, 0 ); DosSemWait( &PumpMessageDoneSem, SEM_INDEFINITE_WAIT ); DosSemSet( &PumpMessageDoneSem ); return( result ); } }
static VOID APIRET DoDebugRequests( VOID ) { for( ;; ) { DosSemWait( &DebugReqSem, SEM_INDEFINITE_WAIT ); DosSemSet( &DebugReqSem ); InDosDebug = TRUE; DebugReqResult = Call32BitDosDebug( DebugReqBuff ); InDosDebug = FALSE; if( IsPMDebugger() ) { WinPostMsg( HwndDebugger, WM_QUIT, 0, 0 ); } else { DosSemClear( &DebugDoneSem ); } } }
/* * This function handles automatic buffer preservation. It runs in its * own thread, which is only awake when keystrokes >= PSVKEYS and the * main thread is waiting for keyboard input. Even then, it spends * most of its time asleep. */ static void FAR psvhandler() { for (;;) { long sleeptime; DosSemWait(psvsema, SEM_INDEFINITE_WAIT); DosSemRequest(control, SEM_INDEFINITE_WAIT); /* * Start of critical section. */ if (keystrokes < PSVKEYS) { sleeptime = 0; /* * If we haven't had at least PSVKEYS * keystrokes, psvsema should be set. */ DosSemSet(psvsema); } else if ((sleeptime = (long) Pn(P_preservetime) * 1000 - CLK2MS(clock() - lastevent)) <= 0) { /* * If Pn(P_presevetime) seconds haven't yet * elapsed, sleep until they should have - but * NOT within the critical section (!). * * Otherwise do automatic preserve. * * exPreserveAllBuffers() should reset keystrokes to 0. */ (void) exPreserveAllBuffers(); sleeptime = 0; } /* * End of critical section. */ DosSemClear(control); /* * Sleep if we have to. */ if (sleeptime != 0) DosSleep(sleeptime); } }
static trap_retval DoRemoteGet( byte *rec, trap_elen len ) { int i; int p; unsigned recvd; unsigned got; putstring( "RemoteGet\r\n" ); putconnstatus( Connection ); len = len; recvd = 0; for( ;; ) { DosSemSet( &RecvSem ); i = NUM_REC_BUFFS-1; p = -1; for( ;; ) { if( i < 0 ) { if( p != -1 ) break; DosSemWait( &RecvSem, 1000 ); i = NUM_REC_BUFFS-1; } if( !InUse( RecECB[i] ) ) { if( p == -1 || LOWER_SEQ( RecHead[i].sequenceNumber, RecHead[p].sequenceNumber ) ) { p = i; } } --i; } got = _SWAPINT( RecHead[p].packetLen ) - sizeof( RecHead[p] ); _fmemcpy( rec, Buffer[p], got ); recvd += got; PostAListen( p ); if( got != MAX_DATA_SIZE ) break; rec += got; } putstring( "Done RemoteGet\r\n" ); return( recvd ); }
static void far Broadcast( void ) { _INITIPXECB( SAP ); FillArray( SAPHead.destNode, 0xff ); SAPHead.destSocket = SAP_SOCKET; SAPHead.infoType = _SWAPINT( 0x2 ); SAPHead.serverType = DBG_SERVER_TYPE; IpxGetInternetworkAddress( (PUCHAR)&SAPHead.addrNet ); SAPHead.addrSocket = IPXSocket; SAPHead.intermediateNetworks = _SWAPINT( 0x1 ); AssignArray( SAPECB.immediateAddress, SAPHead.destNode ); for( ;; ) { IpxSend( IPXSocket, &SAPECB ); DosSemClear( &BroadCastStart ); DosSemWait( &BroadCastStop, 60000 ); if( ServerDie ) { SAPHead.intermediateNetworks = _SWAPINT( 0x10 ); IpxSend( IPXSocket, &SAPECB ); ServerDie |= DIE_BROADCAST; DosExit( EXIT_THREAD, 0 ); } } }
VOID PumpMessageQueue( VOID ) { char class_name[80]; QMSG qmsg; ERRORID err; for( ;; ) { DosSemWait( &PumpMessageSem, SEM_INDEFINITE_WAIT ); DosSemSet( &PumpMessageSem ); WinThreadAssocQueue( GUIGetHAB(), GUIPMmq ); while( WinGetMsg( GUIGetHAB(), &qmsg, 0L, 0, 0 ) ) { WinQueryClassName( qmsg.hwnd, sizeof( class_name ), class_name ); if( strcmp( class_name, "GUIClass" ) == 0 || strcmp( class_name, "WTool" ) == 0 ) { WinDefWindowProc( qmsg.hwnd, qmsg.msg, qmsg.mp1, qmsg.mp2 ); } else { WinDispatchMsg( GUIGetHAB(), &qmsg ); } } WinThreadAssocQueue( GUIGetHAB(), NULL ); err = WinGetLastError( GUIGetHAB() ); DosSemClear( &PumpMessageDoneSem ); } }
/* * netwaitany_async - wait for any async command completion * * Returns address of any completed NCB * If more than one, one with lowest sequence number is returned. */ struct ncb_a * netwaitany_async( long waitmaxtime ) /* max time to wait for any cmd completion */ { register struct ncb_a *ncbp; int muxsemcnt; #ifdef NT LONG rc; #else int rc; #endif #ifdef DEBUG1 int i; #endif struct ncb_a *rncbp; /* ncb pointer to be returned */ unsigned long seqno; /* sequence number */ if (async_ncbs_inited == 0) { #ifdef DEBUG printf("never any async commands in progress.\n"); #endif return ( NULL ); /* nothing to wait on */ } while (1) { lockncbpool(); muxsemcnt = 0; rncbp = NULL; for (ncbp = &asyncncbs[0]; ncbp < &asyncncbs[num_async_ncbs]; ncbp++) { if (ncbp->ncb_status == NCB_INUSE) { /* found an async ncb with command in progress - check complete */ if (ncbp->ncb_done != NRC_PENDING) { /* NCB says it is complete (believe it) */ if ((rncbp == NULL) || (ncbp->ncb_seqno < seqno)) { rncbp = ncbp; /* best match so far */ seqno = ncbp->ncb_seqno; } } else if (rncbp == NULL) { /* no completed commands found so far and */ /* command still pending - add to mux wait list */ ncb_wlist.ncbw_ent[muxsemcnt].ncbw_res = 0; ncb_wlist.ncbw_ent[muxsemcnt].ncbw_sem = ncbp->ncb_sem_a; muxsemcnt++; } } } if (rncbp != NULL) { rncbp->ncb_status = NCB_RETURNED; unlockncbpool(); return ( rncbp ); /* got a live one */ } unlockncbpool(); if (muxsemcnt == 0) { #ifdef DEBUG printf("no async commands in progress.\n"); #endif return ( NULL ); /* none currently in progress */ } if (muxsemcnt == 1) { #ifdef OS2 rc = DosSemWait ( (HSEM) ncb_wlist.ncbw_ent[0].ncbw_sem, /* sem handle */ (long) waitmaxtime); /* max time to wait for sem to clear */ #elif defined NT if (0 > (rc = (LONG) WaitForSingleObject ( ncb_wlist.ncbw_ent[0].ncbw_sem, // event waitmaxtime ) ) ) { fprintf ( stderr, "Single event wait failed (%d)\n", GetLastError() ); exit (GetLastError()); } #endif } else { ncb_wlist.ncbw_semcnt = (short)muxsemcnt; #ifdef DEBUG1 if (tracencb) { printf("Waiting sems "); for (i = 0; i < muxsemcnt; i++) { printf("%lx ", ncb_wlist.ncbw_ent[i].ncbw_sem); } } #endif #ifdef OS2 rc = DosMuxSemWait ( (PUSHORT) &muxsemcnt, /* we ignore the sem index */ (unsigned FAR *) &ncb_wlist, /* list of semaphores waiting for */ waitmaxtime); /* max time to wait */ } if (rc) { /* none of the commands completed in time specified */ #ifdef DEBUG printf("None of commands completed in time specified.\n"); #endif return ( NULL ); } #elif defined NT if (0 > (rc = (LONG) WaitForMultipleObjects ( muxsemcnt, (LPHANDLE) &ncb_wlist, // event array FALSE, waitmaxtime ) ) ) { fprintf ( stderr, "Multiple event wait failed (%d)\n", GetLastError() ); exit (GetLastError()); } } if ( rc == WAIT_TIMEOUT) { return ( NULL ); } #endif /* loop back and find the one completed */ #ifdef DEBUG1 if (tracencb) { printf("- One (or more) completed.\n"); } #endif }
VOID FAR PMfrThread (VOID) { int sub_rc; habThread = WinInitialize(0); WinGetLastError(habThread); /* get the memory DC */ cp.hdcMemory = DevOpenDC (habThread, OD_MEMORY, "*", 0L, NULL, NULL) ; /* this says that we don't have a PS yet; not one to destroy */ cp.hpsMemory = (HPS) NULL; /* let each sub-driver have a crack at it now */ PrintDriverInit(); CalcDriverInit(); /* Initialization here is done. Post main thread that we are going to work */ WinPostMsg(cp.hwnd, WM_THRD_POST, MPFROM2SHORT(SUB_INIT_DONE, 0), MPFROMP(NULL) ); for (;;) { /* wait for something to do */ DosSemWait (&cp.ulSemTrigger, SEM_INDEFINITE_WAIT) ; /* take an early exit for Shutdown */ if (cp.sSubAction == SUB_ACT_TERM) break; /* posted out of wait. do something */ switch(cp.sSubAction) { case SUB_ACT_CALC: sub_rc = CalcDriver(); break; case SUB_ACT_PRINT: sub_rc = PrintDriver(); break; case SUB_ACT_SAVE: sub_rc = SaveDriver(); break; case SUB_ACT_LOAD: sub_rc = LoadDriver(); break; default: sub_rc = 0x9999; /* let the main task figure it out */ break; } /* test here for shutdown also */ if (cp.sSubAction == SUB_ACT_TERM) break; /* not shutdown. */ /* indicate ready for the next cycle */ DosSemSet (&cp.ulSemTrigger) ; WinPostMsg (cp.hwnd, WM_THRD_POST, MPFROM2SHORT(sub_rc, 0) , MPFROMP(NULL) ) ; } /* shutdown has been triggered. release resources obtained by us. NOTE: Serialize using DosEnterCritSec so that the main thread is dormant until we get everything cleaned up and go away. The main thread will be re-dispatched following our final DosExit. */ DosEnterCritSec(); if (cp.hpsMemory != (HPS) 0) { /* protection from a failed WM_CREATE or IDM_GO */ GpiSetBitmap(cp.hpsMemory, (HBITMAP) NULL); GpiDestroyPS(cp.hpsMemory); GpiDeleteBitmap (cp.hbmMemory); } cp.hpsMemory = (HPS) 0; if ( cp.pixels != NULL) hfree(cp.pixels); cp.pixels = NULL; if (cp.hdcMemory != (HDC) 0) DevCloseDC (cp.hdcMemory); cp.hdcMemory = (HDC) 0; /* say good-bye to PM */ WinTerminate(habThread); /* flag we done */ DosSemClear ((HSEM) &cp.ulSemSubEnded); /* and go away */ DosExit(EXIT_THREAD, 0); }
/* * inchar() - get a character from the keyboard. * * Timeout not implemented yet for OS/2. */ int inchar(long mstimeout) { for (;;) { KBDKEYINFO k; bool_t mstatus, psvstatus; flush_output(); mstatus = (usemouse && State == NORMAL); psvstatus = (keystrokes >= PSVKEYS); /* * We don't have to give control to any other thread * if neither of these conditions is true. */ if (mstatus || psvstatus) { #ifndef NOMOUSE if (mstatus) showmouse(); #endif if (psvstatus && DosSemWait(psvsema, SEM_IMMEDIATE_RETURN) == ERROR_SEM_TIMEOUT) { /* * If psvsema is set, clear it. */ DosSemClear(psvsema); } DosSemClear(control); } /* * Start of non-critical section. * * Wait for character from keyboard. */ KbdCharIn((PKBDKEYINFO) &k, IO_WAIT, 0); /* * End of non-critical section. */ if (mstatus || psvstatus) { DosSemRequest(control, SEM_INDEFINITE_WAIT); #ifndef NOMOUSE if (mstatus) hidemouse(); #endif } if (++keystrokes >= PSVKEYS) lastevent = clock(); /* * Now deal with the keypress information. */ if ((unsigned char) k.chChar == (unsigned char) 0xe0) { /* * It's (probably) a function key. */ if (k.chScan == 0x53) /* * It's the delete key. */ return State == NORMAL ? 'x' : '\b'; /* else */ if (State == NORMAL) { /* * Assume it must be a function key. */ switch (k.chScan) { case 0x3b: return(K_HELP); /* F1 key */ case 0x47: return(K_HOME); /* home key */ case 0x48: return(K_UARROW); /* up arrow key */ case 0x49: return(K_PGUP); /* page up key */ case 0x4b: return(K_LARROW); /* left arrow key */ case 0x4d: return(K_RARROW); /* right arrow key */ case 0x4f: return(K_END); /* end key */ case 0x50: return(K_DARROW); /* down arrow key */ case 0x51: return(K_PGDOWN)); /* page down key */ case 0x52: return(K_INSERT); /* insert key */ default: /* just ignore it ... */ continue; } /* * If we aren't in command mode, 0xe0 * is a perfectly legitimate * character, & we can't really tell * whether or not it's supposed to be * a function key, so we just have to * return it as is. */ } } return (unsigned char) k.chChar; } }
unsigned int CallDosDebug( dos_debug __far *buff ) { QMSG qmsg; int num_paints; int i; struct { RECTL rcl; HWND hwnd; } paints[MAX_PAINTS]; HPS ps; char class_name[80]; TID tid; if( !IsPMDebugger() ) { return( Call32BitDosDebug( buff ) ); } switch( buff->Cmd ) { case DBG_C_ClearWatch: case DBG_C_Freeze: case DBG_C_LinToSel: case DBG_C_NumToAddr: case DBG_C_ReadCoRegs: case DBG_C_ReadMemBuf: case DBG_C_ReadMem_D: case DBG_C_ReadReg: case DBG_C_SelToLin: case DBG_C_SetWatch: case DBG_C_ThrdStat: case DBG_C_WriteCoRegs: case DBG_C_WriteMemBuf: case DBG_C_WriteMem_D: case DBG_C_WriteReg: return( Call32BitDosDebug( buff ) ); } switch( buff->Cmd ) { case DBG_C_Go: case DBG_C_SStep: case DBG_C_Term: ReleaseQueue( buff->Pid, buff->Tid ); } DebugReqBuff = buff; StopBuff = *buff; DosSemSet( &DebugDoneSem ); DosSemClear( &DebugReqSem ); num_paints = 0; if( IsPMDebugger() ) { while( WinGetMsg( HabDebugger, &qmsg, 0L, 0, 0 ) || InDosDebug ) { WinQueryClassName( qmsg.hwnd, MAX_CLASS_NAME, class_name ); switch( qmsg.msg ) { case WM_CHAR: if( ( SHORT1FROMMP( qmsg.mp1 ) & KC_VIRTUALKEY ) && ( SHORT2FROMMP( qmsg.mp2 ) == VK_BREAK ) ) { SetBrkPending(); DosCreateThread( StopApplication, &tid, stack2 + STACK_SIZE ); DosSetPrty( PRTYS_THREAD, PRTYC_TIMECRITICAL, 10, tid ); WakeThreads( StopBuff.Pid ); DosSemWait( &StopDoneSem, SEM_INDEFINITE_WAIT ); DosSemSet( &StopDoneSem ); } break; case WM_COMMAND: CantDoIt(); break; default: if( strcmp( class_name, "GUIClass" ) == 0 || strcmp( class_name, "WTool" ) == 0 ) { switch( qmsg.msg ) { case WM_PAINT: if( num_paints >= MAX_PAINTS ) --num_paints; paints[num_paints].hwnd = qmsg.hwnd; ps = WinBeginPaint( qmsg.hwnd, 0, &paints[ num_paints ].rcl ); GpiErase( ps ); WinEndPaint( ps ); num_paints++; break; case WM_BUTTON1DOWN: case WM_BUTTON2DOWN: case WM_BUTTON3DOWN: CantDoIt(); break; case WM_MOUSEMOVE: { HPOINTER hourglass = WinQuerySysPointer( HWND_DESKTOP, SPTR_WAIT, FALSE ); if( WinQueryPointer( HWND_DESKTOP ) != hourglass ) { WinSetPointer( HWND_DESKTOP, hourglass ); } break; } default: WinDefWindowProc( qmsg.hwnd, qmsg.msg, qmsg.mp1, qmsg.mp2 ); } } else { WinDispatchMsg( HabDebugger, &qmsg ); } } } } else { DosSemWait( &DebugDoneSem, SEM_INDEFINITE_WAIT ); } switch( buff->Cmd ) { case DBG_N_Exception: case DBG_N_AsyncStop: case DBG_N_Watchpoint: AssumeQueue( buff->Pid, buff->Tid ); break; } for( i = 0; i < num_paints; ++i ) { WinInvalidateRect( paints[i].hwnd, &paints[i].rcl, FALSE ); } return( DebugReqResult ); }
USHORT NCBWait(PNCB Ncb, ULONG timeout) { if (timeout == -1) timeout = SEM_INDEFINITE_WAIT; return DosSemWait(&Ncb -> basic_ncb.ncb_semaphore, timeout); }