Ejemplo n.º 1
0
int main(int argc, char *argv[])
{

    if (argc != 2)
    {
        fprintf(stderr, "Usage: %s port\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    int pid = fork();

    if(pid)
    {
        waitpid(pid, NULL, 0);
    }
    else
    {
        pid_t sid = setsid();
        if (sid == (pid_t) -1)
        {
            perror("setsid");
            _exit(EXIT_FAILURE);
        }

        AddrInit();
        SetConnection(argv[1]);

        struct pollfd ufds[MAX_CLIENTS + 1];
        int ufdsCount = 1;

        ufds[0].fd = sfd;
        ufds[0].events = POLLIN;

        gamesCount = 0;
        int curGame = 0;

        int rv;
        for (;;) {

            rv = poll(ufds, ufdsCount + 1, -1);

            if (rv == -1)
            {
                printf("poll Error");
                perror("poll"); // error occurred in poll()
            }
            else
            {
                if (rv > 0)
                {

                    // check for events on soket ( adding new clients)
                    if (ufds[0].revents & POLLIN)
                    {

                        int new_cfd; // client fd
                        struct sockaddr_storage peer_addr;
                        socklen_t addr_size = sizeof(peer_addr);

                        if ( (new_cfd = accept(sfd, (struct sockaddr *) &peer_addr, &addr_size)) == -1)
                        {
                            if(close(sfd) == -1) { _exit(EXIT_FAILURE);}
                            perror("accept fail");
                            return 6;
                        }

                        if (new_cfd < MAX_CLIENTS )
                        {
                            ufds[new_cfd].fd = new_cfd;
                            ufds[new_cfd].events = POLLIN | POLLRDHUP; // check for just normal data
                            ufdsCount = new_cfd;
                            printf("creating new games[%d]\n", new_cfd);
                            games[new_cfd].game_state = 0;

                        }
                        else
                        {
                            printf("New client dismist\n");
                            if(close(new_cfd) == -1) { _exit(EXIT_FAILURE);}
                            continue;
                        }

                        //write_to_client(new_cfd, "cenected to server.\n");
                        printf("New client %d\n", new_cfd);
                        
                        int pair_player;
                        if(new_cfd % 2 == 0)
                        {
                            pair_player = new_cfd + 1;
                            games[new_cfd].setMesToBuf("Please wait for second player.\n"); 
                            ufds[new_cfd].events |= POLLOUT;


                            continue;
                        }
                        else
                        {
                            pair_player = new_cfd - 1;
                        }

                        games[new_cfd].game_state = 1;
                        games[pair_player].game_state = 1;
                        games[new_cfd].setMesToBuf("Ready to play.\nYour tearn.\n");
                        games[pair_player].setMesToBuf("Ready to play.\nYour tearn.\n");
                        ufds[new_cfd].events |= POLLOUT;
                        ufds[pair_player].events |= POLLOUT;
                        continue;


                    }

                    int i;
                    char mes = ' ';
                    for (i = 1; i <= ufdsCount; ++i)
                    {

                        if (ufds[i].revents & POLLRDHUP)
                        {
                            printf("POLLRDHUP ivent\n");

                            int pair_player;
                            if(i % 2 == 0)
                            {
                                pair_player = i + 1;
                            }
                            else
                            {
                                pair_player = i - 1;
                            }

                            if(close(i) == -1) { _exit(EXIT_FAILURE);}
                            if(close(pair_player) == -1) { _exit(EXIT_FAILURE);}

                            //games[pair_player].setMesToBuf("You partner is off, game over.\n");

                            ufds[i].fd = -1;
                            ufds[i].events = 0;
                            ufds[pair_player].fd = -1;
                            ufds[pair_player].events = 0;

                            games.erase(i);
                            games.erase(pair_player);
                            printf("Game %d end %d is over. One of the players is off.\n", i, pair_player);
                            continue;

                        }

                        if (ufds[i].revents & POLLOUT)
                        {
                            //printf("POLLOUT ivent\n");
                            if (games[i].len_out != 0)
                            {
                                int writen = write(ufds[i].fd, games[i].buf_out, games[i].len_out);
                                //int writen = write(ufds[i].fd, "meage\n", 6);
                                if (writen == -1)
                                {
                                    printf("Write error\n");
                                    //handle_error("write", ufds, inputs, i, &nfds);
                                }
                                else
                                {
                                    games[i].len_out -= writen;
                                    printf("write game[%d].buf_out:%s, %zu\n", i, games[i].buf_out, games[i].len_out);
                                    if (games[i].len_out == 0) {
                                        ufds[i].events = POLLIN | POLLRDHUP;
                                    }
                                }
                            }
                        }

                        if (ufds[i].revents & POLLIN)
                        {
                            printf("POLLIN ivent\n");
                            nread = read(ufds[i].fd, games[i].buf_in + games[i].len_in, BUF_SIZE - games[i].len_in);


                            if (nread == -1)
                            {
                                printf("reading tearn error\n");
                                continue;               /* Ignore failed request */
                            }

                            if (games[i].len_in + nread < BUF_SIZE)
                            {
                                games[i].len_in += nread;
                            }
                            else
                            {
                                printf("reading from client error, to long mes\n");
                                continue;
                            }


                            printf("Received %zu bytes from soket %d :%s\n", nread, ufds[i].fd, games[i].buf_in);


                            if(games[i].game_state == 1)
                            {
                                if (games[i].state == 0)
                                {
                                    printf("Player%d did tearn: %c\n", i, games[i].mes);
                                    games[i].handleIncomingData(); 
                                    games[i].setMesToBuf("Your turn ecepted.\n");
                                    ufds[i].events |= POLLOUT;

                                }
                                else
                                {
                                    printf("Player%d did extra tearn: %c\n", i, games[i].mes);
                                    games[i].len_in = 0;
                                    games[i].setMesToBuf("Wait till your tern.\n");
                                    ufds[i].events |= POLLOUT;
                                    continue;
                                }
                            }
                            else
                            {
                                printf("Player %d has no partner.\n", i);
                                games[i].setMesToBuf("Wait before second plyer conected.\n");
                                ufds[i].events |= POLLOUT;
                                games[i].len_in = 0;
                                continue;
                            }

                            int pair_player;
                            if(i % 2 == 0)
                            {
                                pair_player = i + 1;
                            }
                            else
                            {
                                pair_player = i - 1;
                            }

                            //assert( games[i].state && games[pair_player].state);

                            if(games[i].state == 1 && games[pair_player].state == 1)
                            {
                                printf("Got bouth tearns.\n", i);
                                int res = Solve(games[i].mes, games[pair_player].mes);
                                if(res == 0)
                                {
                                    games[i].setMesToBuf("Nobody win!\n");
                                    games[pair_player].setMesToBuf("Nobody win!\n");
                                    ufds[i].events |= POLLOUT;
                                    ufds[pair_player].events |= POLLOUT;
                                }
                                if(res == 1)
                                {
                                    games[i].setMesToBuf("You win!\n");
                                    games[pair_player].setMesToBuf("You lose!\n");
                                    ufds[i].events |= POLLOUT;
                                    ufds[pair_player].events |= POLLOUT;
                                }
                                if(res == 2)
                                {
                                    games[i].setMesToBuf("You lose!\n");
                                    games[pair_player].setMesToBuf("You win!\n");
                                    ufds[i].events |= POLLOUT;
                                    ufds[pair_player].events |= POLLOUT;
                                }

                                if(res == -1)
                                {
                                    games[i].setMesToBuf("Wrong licsikon!\n");
                                    games[pair_player].setMesToBuf("Wrong licsikon!\n");
                                    ufds[i].events |= POLLOUT;
                                    ufds[pair_player].events |= POLLOUT;
                                }

                                games[i].state = 0;
                                games[pair_player].state = 0;

                                games[i].setMesToBuf("Next game\nYour tearn!\n");
                                games[pair_player].setMesToBuf("Next game\nYour tearn!\n");
                                ufds[i].events |= POLLOUT;
                                ufds[pair_player].events |= POLLOUT;


                                printf("Game res:%d\n", res);
                            }
                            else
                            {
                                printf("Not bouth stre = 1.\n");
                            }
                        }
                    }
                }
            }
        }

        if(close(sfd) == -1) { _exit(EXIT_FAILURE);}
    }
    _exit(EXIT_SUCCESS);
}
Ejemplo n.º 2
0
void
ProcessSegmentLoadEvent(
    DEBUG_EVENT64 * pde,
    HTHDX           hthdx
    )

/*++

Routine Description:

    This function takes care of dealing with segment load events from
    the wow system.  These come in as exceptions and are translated
    to segment load events in ProcessDebugEvent.

Arguments:

    pde         - Supplies a pointer to the modified debug event

    hthdx       - Supplies the handle to the thread of the debug event

Return Value:

    None.

--*/

{
#if defined(i386) && !defined(WIN32S)

    PDWORDLONG  lpdw = &pde->u.Exception.ExceptionRecord.ExceptionInformation[0];
    int         mode = LOWORD( (DWORD)lpdw[0] );
    int         cb;
    int         cbRead;
    int         b;
    char *      lpb;
    WORD        packetType = tlfDebugPacket;
    HEMI        hemi;
    HPRCX       hprcx = hthdx->hprc;
    int         idx;
    SEGMENT_NOTE        sn;
    ADDR                addr;
    EXPECTED_EVENT *    pee;
    DWORD       eventCode;
    DWORD       subClass;
    LDT_ENTRY   ldt;
    BREAKPOINT *bp;


    DeWow = *pde;

    if ( !FVDMInitDone ) {
        HANDLE  hmodVDM;

        hmodVDM = LoadLibrary("VDMDBG.DLL");

        if ( hmodVDM != (HANDLE)NULL ) {
            FVDMActive = TRUE;

            pfnVDMProcessException = (VDMPROCESSEXCEPTIONPROC)
                GetProcAddress( hmodVDM, "VDMProcessException" );
            pfnVDMGetPointer = (VDMGETPOINTERPROC)
                GetProcAddress( hmodVDM, "VDMGetPointer" );
            pfnVDMGetThreadSelectorEntry = (VDMGETTHREADSELECTORENTRYPROC)
                GetProcAddress( hmodVDM, "VDMGetThreadSelectorEntry" );
            pfnVDMGetThreadContext = (VDMGETCONTEXTPROC)
                GetProcAddress( hmodVDM, "VDMGetContext" );
            pfnVDMSetThreadContext = (VDMSETCONTEXTPROC)
                GetProcAddress( hmodVDM, "VDMSetContext" );
            pfnVDMGetSelectorModule = (VDMGETSELECTORMODULEPROC)
                GetProcAddress( hmodVDM, "VDMGetSelectorModule" );
            pfnVDMEnumProcessWOW = (VDMENUMPROCESSWOWPROC)
                GetProcAddress( hmodVDM, "VDMEnumProcessWOW" );

        } else {
            DMPrintShellMsg( _T("LoadLibrary(VDMDBG.DLL) failed\n"));
        }
        FVDMInitDone = TRUE;
    }
    if ( !FVDMActive ) {
        return;
    } else {
        DebugEvent64To32(pde, &DeWow32);
        (*pfnVDMProcessException)((LPDEBUG_EVENT)&DeWow32);
        DebugEvent32To64(&DeWow32, pde);
    }

    hthdx->fWowEvent   = TRUE;

    switch ( mode ) {
        /*
         *   SEG LOAD:
         *
         *      LOWORD(lpdw[0]) --- DBG_SEGLOAD
         *      HIWORD(lpdw[0]) --- Unused
         *      LOWORD(lpdw[1]) --- Unused
         *      HIWORD(lpdw[1]) --- Unused
         *      lpdw[2]         --- pointer to SEGMENT_NOTE structure
         *      lpdw[3]         --- Reserved
         */

    case DBG_SEGLOAD:
        lpb = (char *) lpdw[2];
        b = DbgReadMemory(hprcx, (UINT_PTR)lpb, &sn, sizeof(sn), &cbRead);

        if ((b == 0) || (cbRead != sizeof(sn))) {
            b = GetLastError();
            AddQueue( QT_CONTINUE_DEBUG_EVENT,
                      hthdx->hprc->pid,
                      hthdx->tid,
                      DBG_CONTINUE,
                      0);
            //hthdx->tstate &= ~(ts_stopped|ts_first|ts_second);
            //hthdx->tstate |= ts_running;
			hthdx->tstate = (TSTATEX)((DWORD)hthdx->tstate & ~(ts_stopped|ts_first|ts_second));
			hthdx->tstate = (TSTATEX)((DWORD)hthdx->tstate | (ts_running));
            return;
        }

        if (sn.FileName[0] == 0) {
            AddQueue( QT_CONTINUE_DEBUG_EVENT,
                      hthdx->hprc->pid,
                      hthdx->tid,
                      DBG_CONTINUE,
                      0);
            //hthdx->tstate &= ~(ts_stopped|ts_first|ts_second);
            //hthdx->tstate |= ts_running;
			hthdx->tstate = (TSTATEX)((DWORD)hthdx->tstate & ~(ts_stopped|ts_first|ts_second));
			hthdx->tstate = (TSTATEX)((DWORD)hthdx->tstate | (ts_running));
            return;
        }
        cb = _tcslen(sn.FileName)+1;

        idx = LookupDllName(hprcx, sn.FileName);

        if ( idx != -1 ) {
            if (hprcx->rgDllList[idx].fReal) {
                //
                //  Changing from real to protected mode. We don't
                //  support this, so we'll throw away what we have
                //  and start from scratch.
                //
                WORD w = (WORD)idx;

                DMSendDebugPacket(dbceModFree16,
                                  hprcx->hpid,
                                  hthdx->htid,
                                  sizeof(WORD),
                                  &w
                                  );

                RemoveDllName( hprcx, idx );
                idx = -1;
            }
        }

        if (idx == -1) {

            LPMODULELOAD lpmdl;

            cb = cb + sizeof(MODULELOAD) + (sn.Segment+1)*sizeof(OBJD);

            lpmdl = (LPMODULELOAD) MHAlloc(cb);

            lpmdl->cobj = sn.Segment+1;

            lpmdl->rgobjd[sn.Segment].wSel = sn.Selector1;
            lpmdl->rgobjd[sn.Segment].cb = (DWORD) -1;
            lpmdl->rgobjd[sn.Segment].wPad = 1;

            lpmdl->mte = InsertDllName(hprcx, sn.FileName);
            _tcscpy((char *) &lpmdl->rgobjd[lpmdl->cobj], sn.FileName);

            lpmdl->fRealMode = FALSE;
            lpmdl->fFlatMode = FALSE;
            lpmdl->fOffset32 = FALSE;

            DMSendRequestReply(dbcModLoad,
                               hprcx->hpid,
                               hthdx->htid,
                               cb,
                               lpmdl,
                               sizeof(HEMI),
                               &hemi
                               );

            hemi = *((HEMI *) abEMReplyBuf);

            MHFree(lpmdl);

            AddQueue( QT_CONTINUE_DEBUG_EVENT,
                      hthdx->hprc->pid,
                      hthdx->tid,
                      DBG_CONTINUE,
                      0);
            //hthdx->tstate &= ~(ts_stopped|ts_first|ts_second);
            //hthdx->tstate |= ts_running;
			hthdx->tstate = (TSTATEX)((DWORD)hthdx->tstate & ~(ts_stopped|ts_first|ts_second));
			hthdx->tstate = (TSTATEX)((DWORD)hthdx->tstate | (ts_running));

        } else {

            SLI       sli;

            sli.wSelector = sn.Selector1;
            sli.wSegNo = sn.Segment;
            sli.mte = idx;

            DMSendDebugPacket(dbceSegLoad,
                              hprcx->hpid,
                              hthdx->htid,
                              sizeof(SLI),
                              &sli
                              );
        }

        break;

        /*
         *   SEGMOVE:
         *
         *      This event will be triggered if a selector number
         *      is to be changed.
         *
         *      LOWORD( lpdw[0] ) - SEGMOVE
         *      LOWORD( lpdw[1] ) - old selector number
         *      HIWORD( lpdw[1] ) - new selector number
         */

    case DBG_SEGMOVE:

        lpb = (char *) lpdw[2];
        b = DbgReadMemory(hprcx, (UINT_PTR)lpb, &sn, sizeof(sn), &cbRead);

        if ((b == 0) || (cbRead != sizeof(sn))) {
            b = GetLastError();
            AddQueue( QT_CONTINUE_DEBUG_EVENT,
                      hthdx->hprc->pid,
                      hthdx->tid,
                      DBG_CONTINUE,
                      0);
            //hthdx->tstate &= ~(ts_stopped|ts_first|ts_second);
            //hthdx->tstate |= ts_running;
			hthdx->tstate = (TSTATEX)((DWORD)hthdx->tstate & ~(ts_stopped|ts_first|ts_second));
			hthdx->tstate = (TSTATEX)((DWORD)hthdx->tstate | (ts_running));
            return;
        }

        if (sn.FileName[0] == 0) {
            AddQueue( QT_CONTINUE_DEBUG_EVENT,
                      hthdx->hprc->pid,
                      hthdx->tid,
                      DBG_CONTINUE,
                      0);
            //hthdx->tstate &= ~(ts_stopped|ts_first|ts_second);
            //hthdx->tstate |= ts_running;
			hthdx->tstate = (TSTATEX)((DWORD)hthdx->tstate & ~(ts_stopped|ts_first|ts_second));
			hthdx->tstate = (TSTATEX)((DWORD)hthdx->tstate | (ts_running));
            return;
        }
        cb = _tcslen(sn.FileName)+1;

        idx = LookupDllName(hprcx, sn.FileName);

        if ( idx != -1 ) {
            SLI       sli;

            assert( sn.Selector1 == 0 );
            sli.wSelector = sn.Selector2;
            sli.wSegNo = sn.Segment;
            sli.mte = idx;

            DMSendDebugPacket(dbceSegMove,
                              hprcx->hpid,
                              hthdx->htid,
                              sizeof(SLI),
                              &sli
                              );
        }

        AddQueue( QT_CONTINUE_DEBUG_EVENT,
                  hthdx->hprc->pid,
                  hthdx->tid,
                  DBG_CONTINUE,
                  0);
        //hthdx->tstate &= ~(ts_stopped|ts_first|ts_second);
        //hthdx->tstate |= ts_running;
		hthdx->tstate = (TSTATEX)((DWORD)hthdx->tstate & ~(ts_stopped|ts_first|ts_second));
		hthdx->tstate = (TSTATEX)((DWORD)hthdx->tstate | (ts_running));

        break;

        /*
         *   SEGFREE:
         *
         *      This event is triggered if a selector is freed
         *
         *      LOWORD( lpdw[0] ) - SEGFREE
         *      HIWORD( lpdw[0] ) - fBPRelease
         *      LOWORD( lpdw[1] ) - selector to be freed
         */

    case DBG_SEGFREE:

        AddQueue( QT_CONTINUE_DEBUG_EVENT,
                  hthdx->hprc->pid,
                  hthdx->tid,
                  DBG_CONTINUE,
                  0);
        //hthdx->tstate &= ~(ts_stopped|ts_first|ts_second);
        //hthdx->tstate |= ts_running;

		hthdx->tstate = (TSTATEX)((DWORD)hthdx->tstate & ~(ts_stopped|ts_first|ts_second));
		hthdx->tstate = (TSTATEX)((DWORD)hthdx->tstate | (ts_running));
        break;

        /*
         *   MODLOAD:
         *
         *      This event is triggered when a new DLL is loaded
         *
         *      LOWORD( lpdw[0] ) - MODLOAD
         *      HIWORD( lpdw[0] ) - length of module name
         *      HIWORD( lpdw[1] ) - selector
         *      lpdw[2]           - address of module name
         *      lpdw[3]           - image length
         *
         */

    case DBG_MODLOAD:

        lpb = (char *) lpdw[2];
        b = DbgReadMemory(hprcx, (UINT_PTR)lpb, &sn, sizeof(sn), &cbRead);

        if ((b == 0) || (cbRead != sizeof(sn))) {
            b = GetLastError();
            AddQueue( QT_CONTINUE_DEBUG_EVENT,
                      hthdx->hprc->pid,
                      hthdx->tid,
                      DBG_CONTINUE,
                      0);
            //hthdx->tstate &= ~(ts_stopped|ts_first|ts_second);
            //hthdx->tstate |= ts_running;
			hthdx->tstate = (TSTATEX)((DWORD)hthdx->tstate & ~(ts_stopped|ts_first|ts_second));
			hthdx->tstate = (TSTATEX)((DWORD)hthdx->tstate | (ts_running));
            return;
        }

        if (sn.FileName[0] == 0) {
            AddQueue( QT_CONTINUE_DEBUG_EVENT,
                      hthdx->hprc->pid,
                      hthdx->tid,
                      DBG_CONTINUE,
                      0);
            //hthdx->tstate &= ~(ts_stopped|ts_first|ts_second);
            //hthdx->tstate |= ts_running;
			hthdx->tstate = (TSTATEX)((DWORD)hthdx->tstate & ~(ts_stopped|ts_first|ts_second));
			hthdx->tstate = (TSTATEX)((DWORD)hthdx->tstate | (ts_running));
            return;
        }

        cb = _tcslen(sn.FileName)+1;
        idx = LookupDllName(hprcx, sn.FileName);

        if (idx == -1) {
            LPMODULELOAD lpmdl;
            cb = cb + sizeof(MODULELOAD);

            lpmdl = (LPMODULELOAD) MHAlloc(cb);

            lpmdl->cobj = 0;

            lpmdl->mte = InsertDllName(hprcx, sn.FileName);

            idx = LookupDllName(hprcx, sn.FileName);

            if ( idx != -1 ) {
                hprcx->rgDllList[idx].fReal = TRUE;
            }

            _tcscpy((char *) &lpmdl->rgobjd[lpmdl->cobj], sn.FileName);

            lpmdl->StartingSegment = sn.Segment;

            lpmdl->fRealMode = TRUE;
            lpmdl->fFlatMode = FALSE;
            lpmdl->fOffset32 = FALSE;

            DMSendRequestReply(dbcModLoad,
                               hprcx->hpid,
                               hthdx->htid,
                               cb,
                               lpmdl,
                               sizeof(HEMI),
                               &hemi
                               );

            MHFree(lpmdl);
        }

        AddQueue( QT_CONTINUE_DEBUG_EVENT,
                  hthdx->hprc->pid,
                  hthdx->tid,
                  DBG_CONTINUE,
                  0);
        //hthdx->tstate &= ~(ts_stopped|ts_first|ts_second);
        //hthdx->tstate |= ts_running;
		hthdx->tstate = (TSTATEX)((DWORD)hthdx->tstate & ~(ts_stopped|ts_first|ts_second));
		hthdx->tstate = (TSTATEX)((DWORD)hthdx->tstate | (ts_running));

        break;

        /*
         *   MODFREE:
         *
         *      This event is triggered when a DLL is unloaded
         *
         *      LOWORD( lpdw[0] ) - MODFREE
         */

    case DBG_MODFREE:
        lpb = (char *) lpdw[2];
        b = DbgReadMemory(hprcx, (UINT_PTR)lpb, &sn, sizeof(sn), &cbRead);

        if ((b == 0) || (cbRead != sizeof(sn))) {
            b = GetLastError();
            AddQueue( QT_CONTINUE_DEBUG_EVENT,
                      hthdx->hprc->pid,
                      hthdx->tid,
                      DBG_CONTINUE,
                      0);
            //hthdx->tstate &= ~(ts_stopped|ts_first|ts_second);
            //hthdx->tstate |= ts_running;
			hthdx->tstate = (TSTATEX)((DWORD)hthdx->tstate & ~(ts_stopped|ts_first|ts_second));
			hthdx->tstate = (TSTATEX)((DWORD)hthdx->tstate | (ts_running));
            return;
        }

        if (sn.FileName[0] == 0) {
            AddQueue( QT_CONTINUE_DEBUG_EVENT,
                      hthdx->hprc->pid,
                      hthdx->tid,
                      DBG_CONTINUE,
                      0);
            //hthdx->tstate &= ~(ts_stopped|ts_first|ts_second);
            //hthdx->tstate |= ts_running;
			hthdx->tstate = (TSTATEX)((DWORD)hthdx->tstate & ~(ts_stopped|ts_first|ts_second));
			hthdx->tstate = (TSTATEX)((DWORD)hthdx->tstate | (ts_running));
            return;
        }
        cb = _tcslen(sn.FileName)+1;

        idx = LookupDllName(hprcx, sn.FileName);

        if (idx != -1) {

            WORD w = (WORD)idx;

            DMSendDebugPacket(dbceModFree16,
                              hprcx->hpid,
                              hthdx->htid,
                              sizeof(WORD),
                              &w
                              );

            RemoveDllName( hprcx, idx );
        }

        AddQueue( QT_CONTINUE_DEBUG_EVENT,
                  hthdx->hprc->pid,
                  hthdx->tid,
                  DBG_CONTINUE,
                  0);
        //hthdx->tstate &= ~(ts_stopped|ts_first|ts_second);
        //hthdx->tstate |= ts_running;

		hthdx->tstate = (TSTATEX)((DWORD)hthdx->tstate & ~(ts_stopped|ts_first|ts_second));
		hthdx->tstate = (TSTATEX)((DWORD)hthdx->tstate | (ts_running));
        break;

        /*
         *  Int 01h break;
         */

    case DBG_SINGLESTEP:
        hthdx->context.ContextFlags = VDMCONTEXT_FULL;
        (*pfnVDMGetThreadContext)(hthdx->hprc->rwHand, hthdx->rwHand, &hthdx->context);

        eventCode = EXCEPTION_DEBUG_EVENT;
        pde->dwDebugEventCode = EXCEPTION_DEBUG_EVENT;
        pde->u.Exception.ExceptionRecord.ExceptionCode = subClass =
            (DWORD)EXCEPTION_SINGLE_STEP;

        /*
         *  They are not clearing the trace bit
         */

        hthdx->context.EFlags &= ~TF_BIT_MASK;
        hthdx->fContextDirty = TRUE;

        AddrInit(&addr, 
                 0, 
                 (SEGMENT) hthdx->context.SegCs, 
                 SE32To64( hthdx->context.Eip ),
                 FALSE, 
                 FALSE, 
                 FALSE, 
                 FALSE
                 );

        bp = FindBP(hthdx->hprc, hthdx, bptpExec, (BPNS)-1, &addr, FALSE);

        if ( bp ) {
            SetBPFlag( hthdx, bp );
        }

        goto dispatch;

    case DBG_TASKSTART:
        hthdx->context.ContextFlags = VDMCONTEXT_FULL;
        (*pfnVDMGetThreadContext)(hthdx->hprc->rwHand, hthdx->rwHand, &hthdx->context);

        eventCode =
        pde->dwDebugEventCode = ENTRYPOINT_DEBUG_EVENT;

        goto dispatch;

    case DBG_TASKSTOP:
    case DBG_DLLSTART:
    case DBG_DLLSTOP:
    case DBG_ATTACH:
        AddQueue( QT_CONTINUE_DEBUG_EVENT,
                  hthdx->hprc->pid,
                  hthdx->tid,
                  DBG_CONTINUE,
                  0);
        hthdx->tstate &= ~(ts_stopped|ts_first|ts_second);
        hthdx->tstate |= ts_running;
        break;


        /*
         *   Int 03h break
         *
         *      LOWORD(lpdw[0])  --- BREAKPOINT
         *      HIWORD(lpdw[0])  --- Protect Mode
         */

    case DBG_BREAK:
        hthdx->context.ContextFlags = VDMCONTEXT_FULL;
        (*pfnVDMGetThreadContext)(hthdx->hprc->rwHand, hthdx->rwHand, &hthdx->context);

        Set_PC(hthdx, PC(hthdx) - 1);
        hthdx->fContextDirty = TRUE;

        eventCode = pde->dwDebugEventCode = BREAKPOINT_DEBUG_EVENT;

        // NOTENOTE --- jimsch -- assuming only 0xcc not 0xcd 0x3 breakpoints

        AddrInit(&addr, 
                 0, 
                 (SEGMENT) hthdx->context.SegCs, 
                 SE32To64( hthdx->context.Eip ),
                 FALSE, 
                 FALSE, 
                 FALSE, 
                 FALSE
                 );

        bp = FindBP(hthdx->hprc, hthdx, bptpExec, (BPNS)-1, &addr, FALSE);

        if ( bp && bp->isStep ) {

            eventCode             = EXCEPTION_DEBUG_EVENT;
            pde->dwDebugEventCode = EXCEPTION_DEBUG_EVENT;

            pde->u.Exception.ExceptionRecord.ExceptionCode =
                subClass = (DWORD)EXCEPTION_SINGLE_STEP;
                RemoveBP(bp);

        } else {

            if ( bp ) {
                SetBPFlag( hthdx, bp );
            }

            pde->u.Exception.ExceptionRecord.ExceptionCode =
                subClass = (DWORD)bp;
        }

        pde->u.Exception.ExceptionRecord.ExceptionAddress = PC(hthdx);

    dispatch:
        hthdx->fAddrIsReal = FALSE;
        hthdx->fAddrIsFlat = FALSE;

        DebugEvent64To32(pde, &DeWow32);
        if ((*pfnVDMGetThreadSelectorEntry)(&DeWow32,
                                            hthdx->rwHand,
                                            (WORD) hthdx->context.SegCs,
                                            &ldt)) {
            if (ldt.HighWord.Bits.Default_Big) {
                hthdx->fAddrOff32 = TRUE;
            } else {
                hthdx->fAddrOff32 = FALSE;
            }
        } else {
            hthdx->fAddrOff32 = FALSE;
        }

        /*
         *  Check if this debug event was expected
         */

        pee = PeeIsEventExpected(hthdx, eventCode, subClass, TRUE);

        /*
         * If it wasn't, run the standard handler with
         * notifications going to the execution model
         */

        assert((0 < eventCode) && (eventCode < MAX_EVENT_CODE));

        if (pee == NULL) {
            if ((hthdx != NULL) && (hthdx->tstate & ts_funceval)) {
                RgfnFuncEventDispatch[eventCode-EXCEPTION_DEBUG_EVENT](pde, hthdx);
            } else {
                DebugDispatchTable[eventCode-EXCEPTION_DEBUG_EVENT](pde,hthdx);
            }
            return;
        }


        /*
         *  If it was expected then call the action
         * function if one was specified
         */

        if (pee->action) {
            (pee->action)(pde, hthdx, 0, pee->lparam);
        }

        /*
         *  And call the notifier if one was specified
         */

        if (pee->notifier) {
            METHOD  *nm = pee->notifier;
            (nm->notifyFunction)(pde, hthdx, 0, nm->lparam);
        }

        free(pee);
        break;

#if 0  // why is this here??
    case DBG_DIVOVERFLOW:
        pde->dwDebugEventCode = 3;
        goto fault_occured;

    case DBG_INSTRFAULT:
        pde->dwDebugEventCode = 1;
        goto fault_occured;
#endif

    case DBG_DIVOVERFLOW:
    case DBG_INSTRFAULT:
    case DBG_GPFAULT:
        pde->dwDebugEventCode = EXCEPTION_DEBUG_EVENT;

#if 0  // why is this here??
    fault_occured:
#endif

        hthdx->context.ContextFlags = VDMCONTEXT_FULL;
        (*pfnVDMGetThreadContext)(hthdx->hprc->rwHand, hthdx->rwHand, &hthdx->context);
        pde->u.Exception.ExceptionRecord.ExceptionCode = 13;

        hthdx->fAddrIsReal = FALSE;
        hthdx->fAddrIsFlat = FALSE;

        DebugEvent64To32(pde, &DeWow32);
        if ((*pfnVDMGetThreadSelectorEntry)(&DeWow32, hthdx->rwHand,
                                      (WORD) hthdx->context.SegCs, &ldt)) {
            if (ldt.HighWord.Bits.Default_Big) {
                hthdx->fAddrOff32 = TRUE;
            } else {
                hthdx->fAddrOff32 = FALSE;
            }
        } else {
            hthdx->fAddrOff32 = FALSE;
        }

        ProcessExceptionEvent(pde, hthdx);
        break;

    default:
        AddQueue( QT_CONTINUE_DEBUG_EVENT,
                  hthdx->hprc->pid,
                  hthdx->tid,
                  DBG_CONTINUE,
                  0);
        hthdx->tstate &= ~(ts_stopped|ts_first|ts_second);
        hthdx->tstate |= ts_running;
        break;
    }
#endif // i386 && !Win32S
    return;
}                               /* ProcessSegmentLoadEvent() */