

//===========================================================//
//  This is source code of cons.dll                          //
//  Made by Dimos (ñ)1999                                    //
//  xdimos@chat.ru   http://www.chat.ru/~xdimos/             //
//===========================================================//
#include <windows.h>

#define BUFFER_SIZE 200

typedef BOOL (CALLBACK *READBYTE)(BYTE);
typedef int (CALLBACK *WRITEBYTE)();


int ConsError=0;
// Struct //
typedef struct {

    READBYTE LPRproc;       //Address of Read proc
    WRITEBYTE LPWproc;      //Address of Write proc 
    
   //some Handles 
	HANDLE  ReadPipeHandle;
    HANDLE  WritePipeHandle;
    HANDLE  ProcessHandle;
    HANDLE  ReadShellThreadHandle;
    HANDLE  WriteShellThreadHandle;

} SESSION_DATA,*PSESSION_DATA;

//This is Error function//
LPSTR WINAPI ConsErr(int Error)
{
	switch(Error)
	{
    case 1:
		return("Failed to execute shell");
    case 2:
        return("Failed to create stdin shell ");
    case 3:
        return("Failed to create stdout shell");
    case 4:
        return("Failed to create read shell thread");
    case 5:
        return("Failed to create write shell thread");
    case 6:
        return("Wait Failed");

	}
    return("No Error");
}
//====================================================//
//              This function is create process       //
//====================================================//
HANDLE StartShell(
                  HANDLE ShellStdinPipeHandle,
                  HANDLE ShellStdoutPipeHandle,
                  LPTSTR exePath)
{
	PROCESS_INFORMATION ProcessInformation;
    STARTUPINFO si;
    HANDLE ProcessHandle = NULL;

    si.cb = sizeof(STARTUPINFO);
	si.lpReserved = NULL;
    si.lpTitle = NULL;
    si.lpDesktop = NULL;
    si.dwX = si.dwY = si.dwXSize = si.dwYSize = 0L;
    si.wShowWindow = SW_HIDE;
    si.lpReserved2 = NULL;
    si.cbReserved2 = 0;

    si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;

    si.hStdInput  = ShellStdinPipeHandle;
    si.hStdOutput = ShellStdoutPipeHandle;

    DuplicateHandle(GetCurrentProcess(), ShellStdoutPipeHandle,
                    GetCurrentProcess(), &si.hStdError,
                    DUPLICATE_SAME_ACCESS, TRUE, 0);


    if (CreateProcess(NULL,exePath, NULL,NULL, TRUE,CREATE_NEW_CONSOLE, NULL, NULL,
                      &si, &ProcessInformation))
	{

		ProcessHandle = ProcessInformation.hProcess;
        CloseHandle(ProcessInformation.hThread);

	}
    else
	{
		 ConsError=1;
	}

    return(ProcessHandle);
}
//====================================================//
//------------ Read process buffer  ------------------//
//====================================================//

static VOID SessionReadShellThreadFn(LPVOID Parameter)
{
    PSESSION_DATA Session=(PSESSION_DATA)Parameter;
    BYTE    Buffer[BUFFER_SIZE];
	BYTE    Buffer1[200];
    DWORD   BytesRead;


    while (PeekNamedPipe(Session->ReadPipeHandle, Buffer, sizeof(Buffer),
                    &BytesRead, NULL, NULL))
	{        
		DWORD BufferCnt;
        ReadFile(Session->ReadPipeHandle,Buffer1,sizeof(Buffer1),
						&BytesRead, NULL);
		
	    for (BufferCnt = 0; BufferCnt < BytesRead; BufferCnt++)
		{
 			Session->LPRproc(Buffer1[BufferCnt]);	//Calling Callback function
		}
		
	}   


    ExitThread(0);
}

//====================================================//
//--------- Write to process buffer ------------------//
//====================================================//

static VOID SessionWriteShellThreadFn(LPVOID Parameter)
{
    PSESSION_DATA Session=(PSESSION_DATA)Parameter;
    BYTE    Buffer[1];
    DWORD   BytesWritten;
    int i=0,d=0,Err;

    while(d!=2)
	{
		 Err=Session->LPWproc(); //Calling Callback function
         if(Err==-1)
			 break;
         Buffer[0]=Err;
         if (! WriteFile(Session->WritePipeHandle, Buffer,sizeof(Buffer),
                            &BytesWritten, NULL))
		 {
			 break;
		 }
	}

    ExitThread(0);
}
///This is main function///
int WINAPI Console(READBYTE lpRProc,WRITEBYTE lpWProc,LPTSTR exePath)
{

    PSESSION_DATA Session = NULL;
    BOOL Result;
    HANDLE ShellStdinPipe = NULL;
    HANDLE ShellStdoutPipe = NULL;
    SECURITY_ATTRIBUTES SecurityAttributes;
    DWORD ThreadId;
    HANDLE HandleArray[3];
    int i;


    Session = (PSESSION_DATA) malloc(sizeof(SESSION_DATA));
    if (Session == NULL)
	{
        return(NULL);
    }

    Session->LPRproc=lpRProc;
    Session->LPWproc=lpWProc;
    Session->ReadPipeHandle  = NULL;
    Session->WritePipeHandle = NULL;

	SecurityAttributes.nLength = sizeof(SecurityAttributes);
    SecurityAttributes.lpSecurityDescriptor = NULL; // Use default ACL
    SecurityAttributes.bInheritHandle = TRUE; // Shell will inherit handles


    //Create read pipe
	Result = CreatePipe(&Session->ReadPipeHandle, &ShellStdoutPipe,
                          &SecurityAttributes, 0);
    if (!Result) 
	{
	   ConsError=2;
       return ConsError;
    }
	//Create write pipe
    Result = CreatePipe(&ShellStdinPipe, &Session->WritePipeHandle,
                        &SecurityAttributes, 0);

    if (!Result) 
	{
	     ConsError=3;
         return ConsError;
	}
    //
    // Start shell
    //
    Session->ProcessHandle = StartShell(ShellStdinPipe, ShellStdoutPipe,exePath);
    //====================================================================//
    if(ConsError==1)
		return ConsError;
    CloseHandle(ShellStdinPipe);
    CloseHandle(ShellStdoutPipe);

	SecurityAttributes.nLength = sizeof(SecurityAttributes);
    SecurityAttributes.lpSecurityDescriptor = NULL;
    SecurityAttributes.bInheritHandle = FALSE;

    //Create read thread
	Session->ReadShellThreadHandle =
         CreateThread(NULL, 0,
                     (LPTHREAD_START_ROUTINE) SessionReadShellThreadFn,
                     (LPVOID) Session, 0, &ThreadId);
    if (Session->ReadShellThreadHandle == NULL)
	{
	    ConsError=4;
        return ConsError;
    }
    //Create write thread
    Session->WriteShellThreadHandle =
        CreateThread(NULL, 0,
                     (LPTHREAD_START_ROUTINE) SessionWriteShellThreadFn,
                     (LPVOID) Session, 0, &ThreadId);
    if (Session->WriteShellThreadHandle == NULL)
	{
	    ConsError=5;
        TerminateThread(Session->WriteShellThreadHandle, 0);
        return ConsError;
	} 


    HandleArray[0] = Session->ReadShellThreadHandle;
    HandleArray[1] = Session->WriteShellThreadHandle;
    HandleArray[2] = Session->ProcessHandle;

	Sleep(1000);
	//Whait while thread functions complite
    i = WaitForMultipleObjects(3, HandleArray, FALSE, INFINITE);

        switch (i) {
      case WAIT_OBJECT_0 + 0:
		TerminateThread(Session->WriteShellThreadHandle, 0);
        TerminateProcess(Session->ProcessHandle, 1);        
		break;

      case WAIT_OBJECT_0 + 1:
		TerminateThread(Session->ReadShellThreadHandle, 0);
        TerminateProcess(Session->ProcessHandle, 1);        
		break;
      case WAIT_OBJECT_0 + 2:
        TerminateThread(Session->WriteShellThreadHandle, 0);
        TerminateThread(Session->ReadShellThreadHandle, 0);
		break;

     default:
             ConsError=6;
             return ConsError;
             break;
		}

	//Close threads and Handles
    TerminateThread(Session->WriteShellThreadHandle, 0);
    TerminateThread(Session->ReadShellThreadHandle, 0);

    DisconnectNamedPipe(Session->ReadPipeHandle);
    CloseHandle(Session->ReadPipeHandle);

    DisconnectNamedPipe(Session->WritePipeHandle);
    CloseHandle(Session->WritePipeHandle);


    CloseHandle(Session->ReadShellThreadHandle);
    CloseHandle(Session->WriteShellThreadHandle);

    CloseHandle(Session->ProcessHandle);

    return ConsError;
}
void main()
{

}