#include <stdio.h>
#include <string.h>
#include <memory.h>
#include <process.h>
#include <windows.h>


#define IDB_START   1001                              //開始ボタン
#define IDE_SENDMSG   1002                              //送信文入力用
#define IDE_RECVMSG   1003                              //受信文表示用
#define IDB_SEND      1004                              //送信ボタン


HINSTANCE hInstance;                               
LPSTR lpszClassName="PipeTest";                          
HANDLE pfd_in, pfd_out;   //子プロセスに渡すハンドル
HANDLE fd_read, fd_write;      //親が読み書きに使うハンドル
SECURITY_ATTRIBUTES SA;
STARTUPINFO SI;
PROCESS_INFORMATION PI;
BOOL Flag=TRUE;
HWND hWndStart,hWndSendMsg, hWndRecvMsg, hWndSend;
DWORD dwParam;

LRESULT CALLBACK WindowProc(HWND,UINT,WPARAM,LPARAM);   


int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst,
    LPSTR lpszArgs, int nWinMode)
{
    HWND hWnd;                                          //ウィンドウハンドル
    MSG  msg;                                           //メッセージ
    WNDCLASSEX wc;                                      //ウィンドウクラス

    hInstance = hThisInst;                              //グローバル化

    //ウィンドウクラス定義
    wc.hInstance     = hInstance;                       //インスタンス
    wc.lpszClassName = lpszClassName;                   //クラス名
    wc.lpfnWndProc   = WindowProc;                      //ウィンドウ関数名
    wc.style         = 0;                               //クラススタイル
    wc.cbSize        = sizeof(WNDCLASSEX);              //構造体サイズ
    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION); //アイコンハンドル
    wc.hIconSm       = LoadIcon(NULL, IDI_WINLOGO);     //スモールアイコン
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);     //マウスポインタ
    wc.lpszMenuName  = NULL;                            //メニュー(なし)
    wc.cbClsExtra    = 0;                               //クラス拡張情報
    wc.cbWndExtra    = 0;                               //ウィンドウ拡張情報
    wc.hbrBackground = (HBRUSH) COLOR_WINDOW;           //ウィンドウの背景色
    if(!RegisterClassEx(&wc)) return 0;                 //ウィンドウクラス登録

    //ウィンドウ生成
    hWnd = CreateWindow(
        lpszClassName,                                  //ウィンドウクラス名
        "Chat Program Ver0.1",                          //ウィンドウ名
        WS_DLGFRAME|WS_VISIBLE|WS_SYSMENU,              //ウィンドウ属性
        CW_USEDEFAULT,                                  //ウィンドウ表示位置(X)
        CW_USEDEFAULT,                                  //ウィンドウ表示位置(Y)
        382,                                            //ウィンドウサイズ(X)
        374,                                            //ウィンドウサイズ(Y)
        HWND_DESKTOP,                                   //親ウィンドウハンドル
        NULL,                                           //
        hInstance,                                      //インスタンスハンドル
        NULL                                            //
    );


    ShowWindow(hWnd, nWinMode);                         //ウィンドウ表示モード
    UpdateWindow(hWnd);                                 //ウインドウ更新

 
    while(GetMessage(&msg, NULL, 0, 0)){                //メッセージを取得
        TranslateMessage(&msg);                         //
        DispatchMessage(&msg);                          //メッセージ送る
    }
    return msg.wParam;                                  //プログラム終了
}

//cmd.exeからのデータを読み込みエディットボックスに書きこむスレッド
DWORD WINAPI ReadThread(LPVOID lpvoid){
	char buf[1024];
	DWORD ret;
	while(Flag){
		memset(buf,'\0',sizeof(buf));
		if(ReadFile(fd_write,buf,1024,&ret,NULL)!=FALSE){
			if(ret>0)SetWindowText(hWndRecvMsg,buf);
		}
	}
	ExitThread(TRUE);
	return 0;
}

LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wP, LPARAM lP)
{

    switch(uMsg){
    case WM_CREATE:
        CreateWindow("static", "送信メッセージ ", WS_CHILD|WS_VISIBLE,
            10,  10, 200, 18, hWnd, NULL, hInstance, NULL);
        CreateWindow("static", "受信メッセージ", WS_CHILD|WS_VISIBLE,
            10, 210, 200, 18, hWnd, NULL, hInstance, NULL);

        hWndStart = CreateWindow("button", "開始",
            WS_CHILD|WS_VISIBLE, 220,10,50,25,
            hWnd, (HMENU)IDB_START, hInstance, NULL);


        hWndSendMsg = CreateWindowEx(WS_EX_CLIENTEDGE, "edit", "",
            WS_CHILD|WS_VISIBLE|ES_MULTILINE|WS_DISABLED, 10, 40, 355, 100,
            hWnd, (HMENU)IDE_SENDMSG, hInstance, NULL);

        hWndSend    = CreateWindow("button", "送信",
            WS_CHILD|WS_VISIBLE|WS_DISABLED, 255,190,50,25,
            hWnd, (HMENU)IDB_SEND, hInstance, NULL);

        hWndRecvMsg = CreateWindowEx(WS_EX_CLIENTEDGE, "edit", "",
            WS_CHILD|WS_VISIBLE|ES_MULTILINE|ES_READONLY|ES_WANTRETURN | ES_MULTILINE | ES_AUTOVSCROLL | WS_VSCROLL |
			ES_AUTOHSCROLL | WS_HSCROLL, 10, 230, 355, 100,
            hWnd, (HMENU)IDE_RECVMSG, hInstance, NULL);

        return 0L;

    case WM_COMMAND:
        switch(LOWORD(wP)){
        case IDB_START:              //パイプを作り、子プロセス、データ受信用のスレッドを起こす 　      
            {
    


	    //ハンドルのセキュリティを設定
	    SA.lpSecurityDescriptor = NULL;
	    SA.bInheritHandle       = TRUE;
	    SA.nLength              = sizeof(SA);
    

	    //まずは子プロセスの出力をfd_writeにつなぐ
		    //第１引数が入り口、第２引数が出口のパイプを作成
		    CreatePipe(&fd_write, &pfd_out, &SA, 0);
	    
	    //以上で「pfd_out」と「fd_write」がパイプでつながる。
	    //pfd_out（子どもが書き込む）に来たデータは（親が読み込む）に出てくる



	    //次に子プロセスの入力をにつなぐ
		    //第１引数が入り口、第２引数が出口のパイプを作成
	    	    CreatePipe(&pfd_in, &fd_read, &SA, 0); 

	    //以上で「fd_read」と「pfd_inがパイプでつながる。
	    //fd_read(親が書きこむ)に来たデータはpfd_in（子どもが読み込む）に出てくる

	    ZeroMemory(&SI, sizeof(SI));
	    SI.cb          = sizeof(SI);
	    SI.dwFlags     = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
	    SI.wShowWindow = SW_HIDE;
	    SI.hStdInput   = pfd_in;          //パイプを指定
	    SI.hStdOutput  = pfd_out;          //パイプを指定
	    SI.hStdError   = NULL;               //標準エラー出力はわかりませんでした。
	
	    CreateProcess(NULL, "cmd.exe", NULL, NULL, TRUE, 0, NULL, NULL, &SI, &PI);

     	    //cmd.exeから出てくるデータを読んで表示するスレッドを起こす
	    CreateThread(NULL , 0 , ReadThread,NULL, 0 , &dwParam);

                EnableWindow(hWndSend, TRUE);
	     EnableWindow(hWndSendMsg,TRUE);
	     EnableWindow(hWndStart,FALSE);
	  }
            return 0L;

        case IDB_SEND:                                //子プロセスにデータを送信する
            {
		char buf[1024];
		DWORD len;
		GetWindowText(hWndSendMsg,buf,1024);
		WriteFile(fd_read,buf,strlen(buf),&len,NULL);
            }
            return 0L;
	}        
	return 0L;
    case WM_DESTROY:                                     
        Flag=FALSE;    //スレッドをループから抜けさせる
        PostQuitMessage(0);                        
        return 0L;                                   
    default:
        return DefWindowProc(hWnd, uMsg, wP, lP);       
    }
    return 0L;                                          
}
