// OriginServer.cpp : implementation file
//

#include "stdafx.h"
#include "ODDE.h"
#include <dde.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// OriginServer

const int DDE_TIMEOUT_SECS = 30;

OriginServer::OriginServer()
{
	m_hwndClientDDE = NULL;
	m_hwndServerDDE = NULL;
	m_nAckTimeOut = 30000;// 30 sec

	memset(&m_pi, 0, sizeof(PROCESS_INFORMATION));

	m_cfDataWksheet = RegisterClipboardFormat("DataWorkSheet");

}

OriginServer::~OriginServer()
{
}



BOOL OriginServer::IsServerRunning()
{
	return m_hwndServerDDE? TRUE:FALSE;
}

BOOL OriginServer::IsFirstAttemptToConnect()
{
	if(m_hwndClientDDE)
		return FALSE;
	return TRUE;
}

BOOL OriginServer::IsServerNotFound()
{
	if(!IsServerRunning() && !IsFirstAttemptToConnect())
		return TRUE;

	return FALSE;
}

BOOL OriginServer::ConnectServer(HWND hWnd, LPCTSTR lpCmdLine)
{
	ASSERT(hWnd);
	ASSERT(IsWindow(hWnd));

	if(IsServerRunning())
		return TRUE;

	if(!IsFirstAttemptToConnect())	// already attempted before
		return FALSE;

	m_hwndClientDDE = hWnd;
	// atemp to start
	if(!InitiateConnection())
	{
		if(!StartNewServer(lpCmdLine))
			return FALSE;
		// server running, try again
		if(!CheckInitiateConnection())
			return FALSE;
	}

	return m_hwndServerDDE? TRUE:FALSE;
}

BOOL OriginServer::InitiateConnection()
{
	ATOM	aTopic,aApp;
	
	aApp = ::GlobalAddAtom(szcAppName);
	aTopic = ::GlobalAddAtom(szcTopicName);
	
		/* The DDE connection is set up to
		 * the Application Origin and any topic
		 *
        	 *
        	 * Broadcast it to everyone using SendMessage;
        	 * When we return from this call, hwndSender will be valid.
        	 */
   	m_wAckState = INITIATE;/* so the ACK knows this is a init message */
    ::SendMessage((HWND)-1,WM_DDE_INITIATE,(WPARAM)m_hwndClientDDE,MAKELONG(aApp,aTopic));
	m_wAckState = 0;
		
    if (aApp != NULL)
		GlobalDeleteAtom(aApp);
    if (aTopic != NULL)
		GlobalDeleteAtom(aTopic);	

	return m_hwndServerDDE? TRUE:FALSE;
}

BOOL OriginServer::StartNewServer(LPCTSTR lpCmdLine)
{
//	if(CreateProcess(NULL, szCmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
	STARTUPINFO			si;	
	memset(&si, 0, sizeof(STARTUPINFO));


	if(!CreateProcess(NULL, (LPSTR)lpCmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &m_pi))
	{
		AfxMessageBox(IDS_MSG_NO_CONNECTION);
		return FALSE;
	}
	ASSERT(GetSavedServerProcess());
	return TRUE;
}

BOOL OriginServer::CheckInitiateConnection()
{
	INT	startTime = GetTickCount();
	INT	maxTime = 1000 * DDE_TIMEOUT_SECS; // 30 sec
	/// wait for server 
	while ( !InitiateConnection() )
	{
		MSG		msg;
		if(::PeekMessage(&msg,NULL,0,0,PM_REMOVE))
		{
			::TranslateMessage(&msg);
			::DispatchMessage(&msg);
		}
		if((int)GetTickCount() - startTime > maxTime)
			break;
	}
	return m_hwndServerDDE? TRUE:FALSE;
}

///------------------------- DDE window proc commands
void	OriginServer::On_WM_DDE_ACK(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
	switch(m_wAckState)
	{
	case INITIATE:
		m_hwndServerDDE = (HWND)wParam;  // get the partner's handle
		break;
	default:
	//	ClientAcknowledge(hWnd,(HWND)wParam, lParam, FALSE);
		break;
	}
}

void	OriginServer::On_WM_DDE_TERMINATE(HWND hWnd)
{
	if(!IsServerRunning())
		return;

	ASSERT(hWnd);
	ASSERT(m_hwndClientDDE == hWnd);
	m_bDataTransfer = FALSE;
	PostMessage(m_hwndServerDDE, WM_DDE_TERMINATE, (WPARAM)hWnd, 0L);
	m_hwndServerDDE = NULL;
	m_hwndClientDDE = NULL;
}

// when the client app choose to exit
void	OriginServer::On_WM_CLOSE(HWND hWnd)
{
	if(	m_hwndServerDDE )
	{
		//::SendMessage(m_hwndServerDDE,WM_CLOSE,0,0);
		PostMessage(m_hwndServerDDE, WM_DDE_TERMINATE, (WPARAM)hWnd, 0L);
		// wait for termination to finish
		
		INT	startTime = GetTickCount();
		INT	maxTime = 1000 * DDE_TIMEOUT_SECS; // 30 sec

		while ( m_hwndServerDDE )
		{
			MSG		msg;
			if(::PeekMessage(&msg,NULL,0,0,PM_REMOVE))
			{
				::TranslateMessage(&msg);
				::DispatchMessage(&msg);
			}
			if((int)GetTickCount() - startTime > maxTime)
				break;
		}
		if(m_hwndServerDDE)
			::MessageBox(NULL,"Timeout","DDE Message",MB_OK);
	}


	HANDLE	hProcess;

	if(hProcess = GetSavedServerProcess())
	{
		DWORD	dwExitCode;
		BOOL	bRetGetExitCode = GetExitCodeProcess(hProcess, &dwExitCode);
		BOOL	bRet = TerminateProcess(hProcess, dwExitCode);
		TRACE("Exit code = %d and ret = %d\n",bRetGetExitCode, bRet); 
	}

}



BOOL OriginServer::SendData(HANDLE hData, LPCTSTR lpcszItem, WORD wOriginDDEFormat)
{
		/* we need to specify the name of the worksheet
		 * as our DDE item. This name must match that
		 * in the Origin document that is to receive
		 * the DDE data.
		 */
	ATOM	atomItem = GlobalAddAtom(lpcszItem);

    m_wAckState = POKE;
    SetTimer(m_hwndClientDDE, (UINT)m_hwndServerDDE, m_nAckTimeOut, NULL);

    if (!PostMessage(m_hwndServerDDE, WM_DDE_POKE, (WPARAM)m_hwndClientDDE, PackDDElParam(WM_DDE_POKE, (UINT)hData, atomItem)))
	{
		GlobalDeleteAtom(atomItem);
		return FALSE;
	}
	return TRUE;
}

//IV 04/07/99 t3291 FINISH_MOVE_DDEDEMO_32BIT
BOOL OriginServer::SendCommandString(LPCTSTR lpstrCommand)
{
	if(!IsServerRunning())
		return FALSE;

	if(m_wAckState == EXECUTE)
	{
		AfxMessageBox(IDS_MSG_SCRIPT_SENDIN_BUSY);
		return FALSE;
	}

    LPSTR lpExecuteString;

    HANDLE	hExecuteString;
  
	
	
    if (!(hExecuteString
          = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, (DWORD)lstrlen(lpstrCommand) + 1)))
        return FALSE;
    if (!(lpExecuteString = (LPSTR)GlobalLock(hExecuteString)))
    {
	GlobalFree(hExecuteString);
        return FALSE;
    }
    lstrcpy(lpExecuteString, lpstrCommand);
    GlobalUnlock(hExecuteString);

    m_wAckState = EXECUTE;
    SetTimer(m_hwndClientDDE, (UINT)m_hwndServerDDE, m_nAckTimeOut, NULL);

    //if (!PostMessage(m_hwndServerDDE, WM_DDE_EXECUTE, (WPARAM)m_hwndClientDDE, MAKELONG(0, hExecuteString)))
    if (!PostMessage(m_hwndServerDDE, WM_DDE_EXECUTE, (WPARAM)m_hwndClientDDE, PackDDElParam(WM_DDE_EXECUTE,0, (UINT)hExecuteString)))
	{
	GlobalFree(hExecuteString);
    }

	m_wAckState = 0;
    return(0);
}
//end FINISH_MOVE_DDEDEMO_32BIT

///--------------------------
