// OriginServer.cpp : implementation file // #include "stdafx.h" #include "ODDE.h" #include #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 ///--------------------------