Esempio n. 1
0
void
LogTaskList( void )

/*++

Routine Description:

    This function gets the current task list and logs the process id &
    process name to the log file.

Arguments:

    None.

Return Value:

    None.

--*/

{
    PTASK_LIST   pTask;
    PTASK_LIST   pTaskBegin;
    LONG         NumTasks;


    lprintf( MSG_TASK_LIST );

    pTask = pTaskBegin = GetTaskList( &NumTasks );

    if (pTask == NULL) {
        printf( "ERROR: could not get the task list\n" );
    }

    while (NumTasks--) {
        lprintfs("%4d %s\r\n",pTask->dwProcessId, pTask->ProcessName );
        pTask++;
    }
    lprintfs( "\r\n" );

    free( pTaskBegin );
}
Esempio n. 2
0
BOOL
SymbolEnumFunc(
    LPSTR   SymbolName,
    ULONG   Address,
    ULONG   Size,
    PVOID   Cxt
    )
{
    lprintfs( "%08x %08x   %s\r\n", Address, Size, SymbolName );
    return TRUE;
}
Esempio n. 3
0
VOID
DumpSymbols(
    PDEBUGPACKET dp
    )
{
    IMAGEHLP_MODULE   mi;


    if (SymGetModuleInfo( dp->hProcess, 0, &mi )) {
        lprintf( MSG_SYMBOL_TABLE );
        do {
            lprintfs( "%s\r\n\r\n", mi.ImageName );
            SymEnumerateSymbols( dp->hProcess, mi.BaseOfImage, SymbolEnumFunc, NULL );
        } while( SymGetModuleInfo( dp->hProcess, (DWORD)-1, &mi ));
    }
}
Esempio n. 4
0
void
GetContextForThread( PDEBUGPACKET dp )
{
    PTHREADCONTEXT ptctx = dp->tctx;

    memset(&ptctx->context,0,sizeof(CONTEXT));

    ptctx->context.ContextFlags = CONTEXT_FULL;

    if (!GetThreadContext( ptctx->hThread, &ptctx->context )) {
        lprintfs( ">>>>> GetThreadContext failed: err(%d), hthread(0x%x)\n",
                  GetLastError(), ptctx->hThread );
        ptctx->pc = 0;
        ptctx->frame = 0;
        ptctx->stack = 0;
    } else {
        ptctx->pc =    (DWORD) ptctx->context.Fir;
        ptctx->frame = (DWORD) ptctx->context.IntSp;
        ptctx->stack = (DWORD) ptctx->context.IntSp;
    }

    return;
}
Esempio n. 5
0
// The thread process the user's conversation: Get user's request command, send it
// to scheduler, Get the response code and return it to user.
// The parameter "lpvParam" if the NamedPipe instance handle value.
DWORD WINAPI ClientAgentThread ( LPVOID lpvParam )
{
	LPTS_COM_PROPS lptsComProps;
	REQUEST Request;
	CHAR szBuffer[PIPE_BUFFER_SIZE];
	DWORD cbWriten, cbReaded;
	DWORD dwRetCode;
	BOOL fSuccess;
	BOOL fDirect = TRUE;
	MSG Msg;

#ifdef TREESVR_STANDALONE
	HANDLE hReadPipe, hWritePipe;

	hReadPipe  = ( ( PIPE_STRU * )lpvParam )->hReadPipe;
	hWritePipe = ( ( PIPE_STRU * )lpvParam )->hWritePipe;
#else
	HANDLE hPipe;

	hPipe = (HANDLE) lpvParam;

	// If the parameter lpvParam is an invalid pipe handle.
	if( hPipe == 0 || hPipe == INVALID_HANDLE_VALUE )
		ExitThread( ERROR_INVALID_PARAMETER );
#endif

	GetQueueStatus( QS_SENDMESSAGE ); 
	
	lprintfs( "Client agent thread starts.\n" );
    
	_try {
	// Wait and read the message send by the client, until the client post.

#ifdef TREESVR_STANDALONE
	fSuccess = ReadFile ( hReadPipe,
			szBuffer, 
			PIPE_BUFFER_SIZE,
			&cbReaded,
			NULL );
#else
	fSuccess = ReadFile ( hPipe,
			szBuffer, 
			PIPE_BUFFER_SIZE,
			&cbReaded,
			NULL );
#endif

	if( !fSuccess ) {
#ifdef TREESVR_STANDALONE
//		FlushFileBuffers( hWritePipe );
#else
		FlushFileBuffers( hPipe );
		DisconnectNamedPipe ( hPipe );
		CloseHandle( hPipe );
#endif
		ExitThread( GetLastError() );
	}

	// Get the packet header, analyse the packet information. 
	lptsComProps = (LPTS_COM_PROPS)szBuffer;
	
	// If the user's first packet is not logon information packet,
	// Reject the user's request.
	if( lptsComProps->packetType != pkTS_SYNC_PIPE || 
			lptsComProps->msgType != msgTS_CLIENT_LOGON ) {
		ZeroMemory( szBuffer, PIPE_BUFFER_SIZE );
		lptsComProps->packetType = pkTS_ERROR;
		lptsComProps->msgType = msgTS_ERROR_MSG;
		
		lptsComProps->len = wsprintfA( (LPSTR)(szBuffer+sizeof( TS_COM_PROPS )),
				"User can not access the server before logon." );

#ifdef TREESVR_STANDALONE
		fSuccess = WriteFile ( hWritePipe,
				(LPCVOID)szBuffer, 
//				lptsComProps->len+sizeof( TS_COM_PROPS ), 
				PIPE_BUFFER_SIZE,
				&cbWriten,
				NULL );

//		FlushFileBuffers( hWritePipe );
#else
		fSuccess = WriteFile ( hPipe,
				(LPCVOID)szBuffer, 
				lptsComProps->len+sizeof( TS_COM_PROPS ), 
				&cbWriten,
				NULL );

		FlushFileBuffers( hPipe );
		DisconnectNamedPipe ( hPipe );
		CloseHandle( hPipe );
#endif
		
		ExitThread( TERR_NOT_LOGON );
	}

#ifndef TREESVR_STANDALONE
	// Add by Jingyu Niu, 2000.08.25, for support single user mode.
	if( singleUserMode ) {
		ZeroMemory( szBuffer, PIPE_BUFFER_SIZE );
		lptsComProps->packetType = pkTS_SYNC_PIPE;
		lptsComProps->msgType = msgTS_LOGON_ERROR;
		lptsComProps->lp = 0x10000;
		
		lptsComProps->len = wsprintfA( (LPSTR)(szBuffer+sizeof( TS_COM_PROPS )),
			"Server now running in single user mode, not accept connect request." );

#ifdef TREESVR_STANDALONE
		fSuccess = WriteFile ( hWritePipe,
				(LPCVOID)szBuffer, 
//				lptsComProps->len+sizeof( TS_COM_PROPS ), 
				PIPE_BUFFER_SIZE,
				&cbWriten,
				NULL );

//		FlushFileBuffers( hWritePipe );
#else
		fSuccess = WriteFile ( hPipe,
				(LPCVOID)szBuffer, 
				lptsComProps->len+sizeof( TS_COM_PROPS ), 
				&cbWriten,
				NULL );

		FlushFileBuffers( hPipe );
		DisconnectNamedPipe ( hPipe );
		CloseHandle( hPipe );
#endif

		ExitThread( 0x10000 );
	}
#endif

	// If the user's logon information packet is invalid,
	// Reject the user's request.
	dwRetCode = MsgToRequest( (LPCSTR)(szBuffer+sizeof( TS_COM_PROPS )), &Request );
	if( dwRetCode != TERR_SUCCESS ) {
		ZeroMemory( szBuffer, PIPE_BUFFER_SIZE );
		lptsComProps->packetType = pkTS_SYNC_PIPE;
		lptsComProps->msgType = msgTS_LOGON_ERROR;
		lptsComProps->lp = dwRetCode;
		
		lptsComProps->len = wsprintfA( (LPSTR)(szBuffer+sizeof( TS_COM_PROPS )),
			"Logon information error(error code:%ld).", dwRetCode );

#ifdef TREESVR_STANDALONE
		fSuccess = WriteFile ( hWritePipe,
				(LPCVOID)szBuffer, 
//				lptsComProps->len+sizeof( TS_COM_PROPS ), 
				PIPE_BUFFER_SIZE,
				&cbWriten,
				NULL );

//		FlushFileBuffers( hWritePipe );
#else
		fSuccess = WriteFile ( hPipe,
				(LPCVOID)szBuffer, 
				lptsComProps->len+sizeof( TS_COM_PROPS ), 
				&cbWriten,
				NULL );

		FlushFileBuffers( hPipe );
		DisconnectNamedPipe ( hPipe );
		CloseHandle( hPipe );
#endif

		ExitThread( dwRetCode );
	}

	// Send the request to scheduler.
	dwRetCode = SendRequest( &Request );
	if( dwRetCode != TERR_SUCCESS ) {
		ZeroMemory( szBuffer, PIPE_BUFFER_SIZE );
		lptsComProps->packetType = pkTS_ERROR;
		lptsComProps->msgType = msgTS_LOGON_ERROR;
		lptsComProps->lp = dwRetCode;
		
		lptsComProps->len = wsprintfA( (LPSTR)(szBuffer+sizeof( TS_COM_PROPS )),
			"Can not logon the server(error code:%ld).", dwRetCode );

#ifdef TREESVR_STANDALONE
		fSuccess = WriteFile ( hWritePipe,
				(LPCVOID)szBuffer, 
//				lptsComProps->len+sizeof( TS_COM_PROPS ), 
				PIPE_BUFFER_SIZE,
				&cbWriten,
				NULL );

//		FlushFileBuffers( hWritePipe );
#else
		fSuccess = WriteFile ( hPipe,
				(LPCVOID)szBuffer, 
				lptsComProps->len+sizeof( TS_COM_PROPS ), 
				&cbWriten,
				NULL );

		FlushFileBuffers( hPipe );
		DisconnectNamedPipe ( hPipe );
		CloseHandle( hPipe );
#endif

		ExitThread( dwRetCode );
	}
	

	ZeroMemory( szBuffer, PIPE_BUFFER_SIZE );
	lptsComProps->packetType = pkTS_SYNC_PIPE;

	if( Request.dwRequest == TERR_SUCCESS ) {
		lptsComProps->msgType = msgTS_LOGON_OK;
		lptsComProps->lp = Request.dwRequestId;
	}
	else { 
		lptsComProps->msgType = msgTS_LOGON_ERROR;
		lptsComProps->lp = Request.dwRequest;
	}
	
#ifdef TREESVR_STANDALONE
	fSuccess = WriteFile ( hWritePipe,
			(LPCVOID)szBuffer, 
//			sizeof( TS_COM_PROPS ), 
			PIPE_BUFFER_SIZE,
			&cbWriten,
			NULL );
#else
	fSuccess = WriteFile ( hPipe,
			(LPCVOID)szBuffer, 
			sizeof( TS_COM_PROPS ), 
			&cbWriten,
			NULL );
#endif

	if( !fSuccess ) {
#ifdef TREESVR_STANDALONE
//		FlushFileBuffers( hWritePipe );
#else
		FlushFileBuffers( hPipe );
		DisconnectNamedPipe ( hPipe );
		CloseHandle( hPipe );
#endif

		ExitThread( GetLastError() );
	}
	
	if( Request.dwRequest != TERR_SUCCESS ) {
#ifdef TREESVR_STANDALONE		
//		FlushFileBuffers( hWritePipe );
#else		
		FlushFileBuffers( hPipe );
		DisconnectNamedPipe ( hPipe );
		CloseHandle ( hPipe );
#endif

		ExitThread( TERR_SUCCESS );
	}

	// Add by NiuJingyu, 1998.03
	GetMessage( &Msg, NULL, TS_SERVICE_START, TS_SERVICE_START );

	dwRetCode = TERR_SUCCESS;

//	lprintfs( "########################## Begin transfer loop.\n" );
	while( 1 ) {
		if( fDirect ) {
			// Client is voluntary.
//		lprintfs( "########################## Read namedpipe.\n" );
#ifdef TREESVR_STANDALONE		
			fSuccess = ReadFile ( hReadPipe,
					szBuffer, 
					PIPE_BUFFER_SIZE,
					&cbReaded,
					NULL );
#else
			fSuccess = ReadFile ( hPipe,
					szBuffer, 
					PIPE_BUFFER_SIZE,
					&cbReaded,
					NULL );
#endif

			if( !fSuccess ) {
				dwRetCode = GetLastError();
				if( dwRetCode == ERROR_BROKEN_PIPE )  { //The pipe has been ended.
					CliSetExchBufError( Request.lpExchangeBuf );
					dwRetCode = TERR_CLIENT_CLOSE;
					break;
				}
			}

#ifdef TREESVR_STANDALONE		
//			FlushFileBuffers ( hWritePipe );
#else
			FlushFileBuffers ( hPipe );
#endif
		
			lptsComProps = (LPTS_COM_PROPS)szBuffer;
			if( lptsComProps->endPacket == '\x0' )
				fDirect = FALSE;

			if( lptsComProps->packetType == pkTS_SYNC_PIPE ) {
				if( lptsComProps->msgType == msgTS_PIPE_CLOSE ) {
					dwRetCode = TERR_SUCCESS;
					break;
				}
			} 

#ifndef TREESVR_STANDALONE
			// Add by Jingyu Niu, 2000.08.25, for support single user mode.
			if( singleUserMode && singleUserThread != GetCurrentThreadId() ) {
				if( fDirect )
					continue;
				else {
					dwRetCode = TERR_SUCCESS;
					break;
				}
			}
#endif

//			lprintfs( "########################## Client write exchange buffer.\n" );
			dwRetCode = CliWriteExchngBuf( Request.lpExchangeBuf, szBuffer, 4096 );
			if( dwRetCode != TERR_SUCCESS ) {
				break;
			}
		}
		else {
			// Service thread is voluntary.
			// Read the packet from service thread.
			dwRetCode = CliReadExchngBuf( Request.lpExchangeBuf, szBuffer, 4096 );
			if( dwRetCode != TERR_SUCCESS )
				break;

			lptsComProps = (LPTS_COM_PROPS)szBuffer;
			if( lptsComProps->endPacket == '\x0' )
				fDirect = TRUE;
	
			if( lptsComProps->packetType == pkTS_SYNC_PIPE ) {
				if( lptsComProps->msgType == msgTS_NO_DATA )
					continue;
			}

#ifndef TREESVR_STANDALONE
			// Add by Jingyu Niu, 2000.08.25, for support single user mode.
			if( singleUserMode && singleUserThread != GetCurrentThreadId() && fDirect ) {
				lptsComProps->packetType = pkTS_SYNC_PIPE;
				lptsComProps->msgType = msgTS_PIPE_CLOSE;
				lptsComProps->lp = 0;
				lptsComProps->len = 0;
				lptsComProps->leftPacket = '\x0';
				lptsComProps->endPacket = '\x0';

				dwRetCode = CliWriteExchngBuf( Request.lpExchangeBuf, szBuffer, 4096 );
				break;
			}
#endif

#ifdef TREESVR_STANDALONE
			fSuccess = WriteFile ( hWritePipe,
					(LPCVOID)szBuffer, 
//					lptsComProps->len+sizeof( TS_COM_PROPS ), 
					PIPE_BUFFER_SIZE,
					&cbWriten,
					NULL );
#else
			fSuccess = WriteFile ( hPipe,
					(LPCVOID)szBuffer, 
					lptsComProps->len+sizeof( TS_COM_PROPS ), 
					&cbWriten,
					NULL );
#endif
			
			if( !fSuccess ) {
				dwRetCode = GetLastError();
				if( dwRetCode == ERROR_NO_DATA ) { // Pipe close in progress.
					dwRetCode = TERR_CLIENT_CLOSE;
					CliSetExchBufError( Request.lpExchangeBuf );
					break;
				}
			}
#ifdef TREESVR_STANDALONE		
//			FlushFileBuffers ( hWritePipe );
#else
			FlushFileBuffers ( hPipe );
#endif
		}
		
		dwRetCode = TERR_SUCCESS;
	}

	if( dwRetCode == TERR_SUCCESS ) {
		ZeroMemory( szBuffer, 4096 );
		lptsComProps->packetType = pkTS_SYNC_PIPE;
		lptsComProps->msgType = msgTS_CLIENT_LOGOFF;
		dwRetCode = CliWriteExchngBuf( Request.lpExchangeBuf, szBuffer, 4096 );
		if( dwRetCode != TERR_SUCCESS )
			CliSetExchBufError( Request.lpExchangeBuf );
	}

	lprintfs( "Client agent thread ends.\n" );

#ifdef TREESVR_STANDALONE		
//	FlushFileBuffers ( hWritePipe );
#else
	FlushFileBuffers ( hPipe );
	DisconnectNamedPipe ( hPipe );
	CloseHandle ( hPipe );
#endif
	}
	_except ( EXCEPTION_EXECUTE_HANDLER ) {
		char szBuffer[256];

		wsprintf( szBuffer, "Client adent thread cause an exception.\n" );
		MessageBox( NULL, szBuffer, "Inspector", MB_OK | MB_ICONSTOP );
	}

	ExitThread( TERR_SUCCESS );

	return  0;

}
Esempio n. 6
0
////////////////////TCP/IP//////////////////////
DWORD WINAPI TcpipSelectConnectThread ( LPVOID lpvParam )
{
	HANDLE 	hThread;
	DWORD 	dwThreadID;
	
	SOCKET 	iSocket;
	SOCKADDR_IN sin;
	int 	err;
	BOOL	fSuccess;
//	DWORD 	dwBytesRead;
	int 	zero;
	SOCKET 	sListener;
	WSADATA WsaData;

    //
    // Create a listening socket that we'll use to accept incoming
    // conections.
	//

	err = WSAStartup( 0x0101, &WsaData );
	if ( err == SOCKET_ERROR ) {
		lprintfs( "WSAStartup failed.\n" );
	}

	sListener = socket( AF_INET, SOCK_STREAM, 0 );
	if ( sListener == INVALID_SOCKET ) {
		return FALSE;
    }

    //
    // Bind the socket to the POP3 well-known port.
    //

    sin.sin_family = AF_INET;
	sin.sin_port = htons( TreeSVR_PORT );
    sin.sin_addr.s_addr = INADDR_ANY;

	err = bind( sListener, (LPSOCKADDR)&sin, sizeof(sin) );
	if ( err == SOCKET_ERROR ) {
        closesocket( sListener );
        return FALSE;
    }

	//
	// Listen for incoming connections on the socket.
    //

    err = listen( sListener, 5 );
    if ( err == SOCKET_ERROR ) {
        closesocket( sListener );
        return FALSE;
    }

    //
    // Loop forever accepting connections from clients.
    //

	while( TRUE ) {
		// Delay a little time, so that current thread can correctly process the
		// user's connection.
		Sleep( 0 );

		// Reset the flag.
		fSuccess = TRUE;

		_try {

			iSocket = accept( sListener, NULL, NULL );
			if ( iSocket == INVALID_SOCKET ) {
				closesocket( sListener );
				fSuccess = FALSE;
				_leave;
			}

			zero = 0;
			err = setsockopt( iSocket, SOL_SOCKET, SO_SNDBUF, (char *)&zero, sizeof(zero) );
			if ( err == SOCKET_ERROR ) {
				closesocket( iSocket );
				closesocket( sListener );
				fSuccess = FALSE;
				_leave;
			}

			hThread = CreateThread( NULL,
									0,
									(LPTHREAD_START_ROUTINE)TcpipClientAgentThread,
									(LPVOID)iSocket,
									0,
									&dwThreadID );

			if( hThread == NULL ) {
					fSuccess = FALSE;
					_leave;
			} else
					CloseHandle( hThread );
		}

		_finally {
			if( fSuccess == FALSE ) {
				// if a NamedPipe instance create and not successfull processed,
				// Close it.
				if ( iSocket != INVALID_SOCKET ) {
					closesocket( iSocket );
				}
			}
		}
	}

	if ( iSocket != INVALID_SOCKET ) {
		closesocket( sListener );
	}

	return TERR_SUCCESS;
}
Esempio n. 7
0
/////////////////////////////////////////////////////////////////////////
// The thread process the user's conversation: Get user's request command, send it
// to scheduler, Get the response code and return it to user.
// The parameter "lpvParam" if the NamedPipe instance handle value.
DWORD WINAPI TcpipClientAgentThread( LPVOID lpvParam )
{
	LPTS_COM_PROPS lptsComProps;
	REQUEST 	Request;
	CHAR 		szBuffer[PIPE_BUFFER_SIZE];
	DWORD 		cbWriten, cbReaded;
	DWORD 		dwRetCode;
	int 		iRet;
	BOOL 		fDirect = TRUE;
	MSG 		Msg;
	SOCKET 		iSocket;

	iSocket = (SOCKET)lpvParam;

	// If the parameter lpvParam is an invalid pipe handle.
	//if( iSocket == SOCKET_ERROR )
	//	ExitThread( ERROR_INVALID_PARAMETER );

	GetQueueStatus( QS_SENDMESSAGE );

	lprintfs( "Client agent thread starts.\n" );

	_try {
	// Wait and read the message send by the client, until the client post.

	cbReaded = recvPacket(iSocket, szBuffer, PIPE_BUFFER_SIZE);
	//if( cbReaded == SOCKET_ERROR ) {
	if( cbReaded <= 0 ) {
		ExitThread( GetLastError() );
	}

	// Get the packet header, analyse the packet information.
	lptsComProps = (LPTS_COM_PROPS)szBuffer;

	// If the user's first packet is not logon information packet,
	// Reject the user's request.
	if( lptsComProps->packetType != pkTS_SYNC_PIPE ||
						lptsComProps->msgType != msgTS_CLIENT_LOGON ) {
		ZeroMemory( szBuffer, PIPE_BUFFER_SIZE );
		lptsComProps->packetType = pkTS_ERROR;
		lptsComProps->msgType = msgTS_ERROR_MSG;

		lptsComProps->len = wsprintfA( (LPSTR)(szBuffer+sizeof( TS_COM_PROPS )),
				"User can not access the server before logon." );

		iRet = sendPacket(iSocket, szBuffer,
							 lptsComProps->len+sizeof( TS_COM_PROPS ) );
		//if( iRet == SOCKET_ERROR ) {
		if( iRet <= 0 ) {
			ExitThread( GetLastError() );
		}

		ExitThread( TERR_NOT_LOGON );
	}

#ifndef TREESVR_STANDALONE
	// Add by Jingyu Niu, 2000.08.25, for support single user mode.
	if( singleUserMode ) {
		ZeroMemory( szBuffer, PIPE_BUFFER_SIZE );
		lptsComProps->packetType = pkTS_SYNC_PIPE;
		lptsComProps->msgType = msgTS_LOGON_ERROR;
		lptsComProps->lp = 0x10000;
		
		lptsComProps->len = wsprintfA( (LPSTR)(szBuffer+sizeof( TS_COM_PROPS )),
			"Server now running in single user mode, not accept connect request." );

		cbWriten = sendPacket( iSocket, szBuffer,
							 lptsComProps->len+sizeof(TS_COM_PROPS) );
		//if( cbWriten == SOCKET_ERROR ) {
		if( cbWriten <= 0 ) {
			ExitThread( GetLastError() );
		}

		ExitThread( 0x10000 );
	}
#endif
	
	// If the user's logon information packet is invalid,
	// Reject the user's request.
	dwRetCode = MsgToRequest( (LPCSTR)(szBuffer+sizeof( TS_COM_PROPS )), &Request );
	if( dwRetCode != TERR_SUCCESS ) {
		ZeroMemory( szBuffer, PIPE_BUFFER_SIZE );
		lptsComProps->packetType = pkTS_SYNC_PIPE;
		lptsComProps->msgType = msgTS_LOGON_ERROR;
		lptsComProps->lp = dwRetCode;
		
		lptsComProps->len = wsprintfA( (LPSTR)(szBuffer+sizeof( TS_COM_PROPS )),
			"Logon information error(error code:%ld).", dwRetCode );

		cbWriten = sendPacket( iSocket, szBuffer,
							 lptsComProps->len+sizeof(TS_COM_PROPS) );
		//if( cbWriten == SOCKET_ERROR ) {
		if( cbWriten <= 0 ) {
			ExitThread( GetLastError() );
		}

		ExitThread( dwRetCode );
	}
	
	// Send the request to scheduler.
	dwRetCode = SendRequest( &Request );
	if( dwRetCode != TERR_SUCCESS ) {
		ZeroMemory( szBuffer, PIPE_BUFFER_SIZE );
		lptsComProps->packetType = pkTS_ERROR;
		lptsComProps->msgType = msgTS_LOGON_ERROR;
		lptsComProps->lp = dwRetCode;
		
		lptsComProps->len = wsprintfA( (LPSTR)(szBuffer+sizeof( TS_COM_PROPS )),
			"Can not logon the server(error code:%ld).", dwRetCode );

		cbWriten = sendPacket( iSocket, szBuffer,
							 lptsComProps->len+sizeof(TS_COM_PROPS) );
		//if( cbWriten == SOCKET_ERROR ) {
		if( cbWriten <= 0 ) {
			ExitThread( GetLastError() );
		}

		ExitThread( dwRetCode );
	}


	ZeroMemory( szBuffer, PIPE_BUFFER_SIZE );
	lptsComProps->packetType = pkTS_SYNC_PIPE;

	if( Request.dwRequest == TERR_SUCCESS ) {
		lptsComProps->msgType = msgTS_LOGON_OK;
		lptsComProps->lp = Request.dwRequestId;
	}
	else {
		lptsComProps->msgType = msgTS_LOGON_ERROR;
		lptsComProps->lp = Request.dwRequest;
	}

	cbWriten = sendPacket( iSocket, szBuffer, sizeof(TS_COM_PROPS) );
	//if( cbWriten == SOCKET_ERROR ) {
	if( cbWriten <= 0 ) {
		ExitThread( GetLastError() );
	}

	if( Request.dwRequest != TERR_SUCCESS ) {
		ExitThread( TERR_SUCCESS );
	}

	// Add by NiuJingyu, 1998.03
	GetMessage( &Msg, NULL, TS_SERVICE_START, TS_SERVICE_START );

	dwRetCode = TERR_SUCCESS;

	while( 1 ) {
		if( fDirect ) {
			cbReaded = recvPacket(iSocket, szBuffer, PIPE_BUFFER_SIZE);
			//if( cbReaded == SOCKET_ERROR ) {
			if( cbReaded <= 0 ) {
				dwRetCode = GetLastError();
				CliSetExchBufError( Request.lpExchangeBuf );
				dwRetCode = TERR_CLIENT_CLOSE;
				break;
			}

			lptsComProps = (LPTS_COM_PROPS)szBuffer;
			if( lptsComProps->endPacket == '\x0' )
				fDirect = FALSE;

			if( lptsComProps->packetType == pkTS_SYNC_PIPE ) {
				if( lptsComProps->msgType == msgTS_PIPE_CLOSE ) {
					dwRetCode = TERR_SUCCESS;
					break;
				}
			} 

#ifndef TREESVR_STANDALONE
			// Add by Jingyu Niu, 2000.08.25, for support single user mode.
			if( singleUserMode && singleUserThread != GetCurrentThreadId() ) {
				if( fDirect )
					continue;
				else {
					dwRetCode = TERR_SUCCESS;
					break;
				}
			}

#endif
			
//			lprintfs( "########################## Client write exchange buffer.\n" );
			dwRetCode = CliWriteExchngBuf( Request.lpExchangeBuf, szBuffer, 4096 );
			if( dwRetCode != TERR_SUCCESS ) {
				break;
			}
		}
		else {
			// Service thread is voluntary.
			// Read the packet from service thread.
			dwRetCode = CliReadExchngBuf( Request.lpExchangeBuf, szBuffer, 4096 );
			if( dwRetCode != TERR_SUCCESS )
				break;

			lptsComProps = (LPTS_COM_PROPS)szBuffer;
			if( lptsComProps->endPacket == '\x0' )
				fDirect = TRUE;
	
			if( lptsComProps->packetType == pkTS_SYNC_PIPE ) {
				if( lptsComProps->msgType == msgTS_NO_DATA )
					continue;
			}

#ifndef TREESVR_STANDALONE
			// Add by Jingyu Niu, 2000.08.25, for support single user mode.
			if( singleUserMode && singleUserThread != GetCurrentThreadId() && fDirect ) {
				lptsComProps->packetType = pkTS_SYNC_PIPE;
				lptsComProps->msgType = msgTS_PIPE_CLOSE;
				lptsComProps->lp = 0;
				lptsComProps->len = 0;
				lptsComProps->leftPacket = '\x0';
				lptsComProps->endPacket = '\x0';

				dwRetCode = CliWriteExchngBuf( Request.lpExchangeBuf, szBuffer, 4096 );
				break;
			}
#endif

			cbWriten = sendPacket( iSocket, szBuffer,
								 lptsComProps->len+sizeof(TS_COM_PROPS) );
			//if( cbWriten == SOCKET_ERROR ) {
			if( cbWriten <= 0 ) {
				dwRetCode = GetLastError();
				CliSetExchBufError( Request.lpExchangeBuf );
				break;
			}
		}

		dwRetCode = TERR_SUCCESS;
	}

	if( dwRetCode == TERR_SUCCESS ) {
		ZeroMemory( szBuffer, 4096 );
		lptsComProps->packetType = pkTS_SYNC_PIPE;
		lptsComProps->msgType = msgTS_CLIENT_LOGOFF;
		dwRetCode = CliWriteExchngBuf( Request.lpExchangeBuf, szBuffer, 4096 );
		if( dwRetCode != TERR_SUCCESS )
			CliSetExchBufError( Request.lpExchangeBuf );
	}

	lprintfs( "Client agent thread ends.\n" );

	}
	_except ( EXCEPTION_EXECUTE_HANDLER ) {
		char szBuffer[256];

		wsprintf( szBuffer, "Client adent thread cause an exception.\n" );
		MessageBox( NULL, szBuffer, "Inspector", MB_OK | MB_ICONSTOP );
	}

	closesocket( iSocket );
	ExitThread( TERR_SUCCESS );

	return  0;

}