home *** CD-ROM | disk | FTP | other *** search
- // BLink.cpp : Defines the initialization routines for the DLL.
- //
-
- #include "stdafx.h"
- #include "BLink.h"
- #include "Link.h"
- #include "assert.h"
- #include "dialogthread.h"
- #include "export.h"
-
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
-
- #define LINKDATASIZE 256
- #define MAXINSTANCES 4
- #define MAXLINKS 20
- #define EVENTTIMEOUT 5000L // 5 seconds
- #define MUTEXTIMEOUT 10000L // 10 seconds
- #define SIZEOFBASICINTEGER 2
- #define SIZEOFBASICLONG 4
- #define SIZEOFBASICREAL 8
- #define SIZEOFBASICSTRING 0
- #define SUCCESS 0
- #define LINKLIMIT 1
- #define INVALIDTYPE 2
- #define INVALIDDIRECTION 3
- #define INVALIDLINKID 4
- #define LINKIDEXISTS 5
- #define SERVEREXISTS 6
- #define NOTSECURE 7
- #define NOCREATELINK 8
- #define WHOLELIST 0
- #define GETID 1
- #define INVALIDOPTION -1
- #define DATAMISMATCH 1
-
- //
- // Note!
- //
- // If this DLL is dynamically linked against the MFC
- // DLLs, any functions exported from this DLL which
- // call into MFC must have the AFX_MANAGE_STATE macro
- // added at the very beginning of the function.
- //
- // For example:
- //
- // extern "C" BOOL PASCAL EXPORT ExportedFunction()
- // {
- // AFX_MANAGE_STATE(AfxGetStaticModuleState());
- // // normal function body here
- // }
- //
- // It is very important that this macro appear in each
- // function, prior to any calls into MFC. This means that
- // it must appear as the first statement within the
- // function, even before any object variable declarations
- // as their constructors may generate calls into the MFC
- // DLL.
- //
- // Please see MFC Technical Notes 33 and 58 for additional
- // details.
- //
-
- /////////////////////////////////////////////////////////////////////////////
- // CBLinkApp
-
- BEGIN_MESSAGE_MAP(CBLinkApp, CWinApp)
- //{{AFX_MSG_MAP(CBLinkApp)
- // NOTE - the ClassWizard will add and remove mapping macros here.
- // DO NOT EDIT what you see in these blocks of generated code!
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
-
- /////////////////////////////////////////////////////////////////////////////
- // CBLinkApp construction
-
- CBLinkApp::CBLinkApp()
- {
- // TODO: add construction code here,
- // Place all significant initialization in InitInstance
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // The one and only CBLinkApp object
-
- CBLinkApp theApp;
-
-
- #pragma data_seg("LinkData")
-
- char g_DataBlock[LINKDATASIZE] = {NULL};
- short g_RequestID = 0;
- short g_RequestInstance = 0;
- short g_StringSize = 0;
- short g_NextInstanceID = 0;
- short g_ServerList[MAXLINKS][2] = {0,0};
- short g_ServerCount = 0;
-
- #pragma data_seg()
-
-
- short g_InstanceID;
- Link* g_pLinks[MAXLINKS] = {NULL};
- short g_LinkCount = 0;
- HANDLE g_hSetupMutex;
- HANDLE g_hMutex;
- HANDLE g_hRequestEvents[MAXINSTANCES];
- HANDLE g_hAnswerEvents[MAXINSTANCES];
- HANDLE g_hShutDown[MAXINSTANCES];
- BOOL g_ListenThread = FALSE;
- BOOL g_StopLinkRequest = FALSE;
- CWinThread * g_pThread;
-
-
- int GetMutex(HANDLE hMutex)
- { DWORD result;
-
- result = WaitForSingleObject(hMutex,MUTEXTIMEOUT); // get mutex for control of data
-
- if (result == WAIT_OBJECT_0)
- { return(1);
- }
- else
- { return(0);
- }
- }
-
- int WaitEvent(HANDLE hEvent)
- { DWORD result;
-
- result = WaitForSingleObject(hEvent,EVENTTIMEOUT); // wait for return signal
-
- if (result == WAIT_OBJECT_0)
- { return(1);
- }
- else
- { return(0);
- }
- }
-
-
- short UpdateID(short index)
- { short result = 0;
-
- if (GetMutex(g_hMutex)) // grab the mutex for shared data access
- { int ServerCheck = 0;
-
- // cycle ServerList to get which instance of basic to request from
- while (ServerCheck < g_ServerCount && g_pLinks[index]->m_LinkID != g_ServerList[ServerCheck][0])
- { ServerCheck++;
- }
- if (ServerCheck == g_ServerCount) // there is no server for this ID
- { ReleaseMutex(g_hMutex);
- return(0);
- }
-
- g_RequestID = g_pLinks[index]->m_LinkID; // place requested ID into shared data for server to see
- g_RequestInstance = g_InstanceID; // send our instance so the server knows who to send back to
-
- SetEvent(g_hRequestEvents[g_ServerList[ServerCheck][1]]); // signal event so request will be processed
-
- if (WaitEvent(g_hAnswerEvents[g_InstanceID])) // wait for answer
- { // get data sent and place in basic variable
- if (g_pLinks[index]->m_DataSize)
- { memcpy(g_pLinks[index]->m_pData,&g_DataBlock,g_pLinks[index]->m_DataSize);
- }
- else
- { strncpy((char *)g_pLinks[index]->m_pData,(char *)&g_DataBlock,g_StringSize);
- short* pStringSize = (short*)((char *)g_pLinks[index]->m_pData - 2);
- *pStringSize = g_StringSize; // update Basic string size
- }
- result = 1;
- }
- else
- { result = 0; // no answer
- }
-
- ReleaseMutex(g_hMutex);
- }
-
- return(result);
- }
-
- short Setlink(short LinkID,void* pData,char* type,char* direction)
- { short size;
- int CheckForID;
- BOOL InFlag = FALSE;
-
- if (g_LinkCount == MAXLINKS) // check to see if at link limit
- { return(LINKLIMIT);
- }
-
- // get size from type param
- if (!stricmp("INTEGER",type))
- { size = SIZEOFBASICINTEGER;
- }
-
- else if (!stricmp("LONG",type))
- { size = SIZEOFBASICLONG;
- }
-
- else if (!stricmp("REAL",type))
- { size = SIZEOFBASICREAL;
- }
-
- else if (!stricmp("STRING",type))
- { size = SIZEOFBASICSTRING;
- }
- else // bad type
- { return(INVALIDTYPE);
- }
-
- if (stricmp("IN",direction) && stricmp("OUT",direction)) // check for valid direction
- { return(INVALIDDIRECTION);
- }
-
- if (LinkID == 0) // do not allow LinkID of 0
- { return(INVALIDLINKID);
- }
-
- for (CheckForID = 0;CheckForID < g_LinkCount;CheckForID++)
- { if (LinkID == g_pLinks[CheckForID]->m_LinkID)
- { return(LINKIDEXISTS);
- }
- }
-
- if (!stricmp("IN",direction))
- { InFlag = TRUE;
- }
-
- g_pLinks[g_LinkCount] = new Link(LinkID,pData,size,InFlag); // create new link object and hold ptr in array
-
- if (g_pLinks != NULL)
- { g_LinkCount++;
-
- if (!stricmp("OUT",direction)) // if OUT direction we need to setup
- { if (GetMutex(g_hMutex)) // secure data
- { int loop;
-
- for (loop = 0;loop < g_ServerCount;loop++) // check to see if link ID already has server
- { if (g_ServerList[loop][0] == LinkID)
- { ReleaseMutex(g_hMutex); // let go of data
- return(SERVEREXISTS);
- }
- }
-
- g_ServerList[g_ServerCount][0] = LinkID; // save data into shared area
- g_ServerList[g_ServerCount][1] = g_InstanceID;
- g_ServerCount++;
-
- ReleaseMutex(g_hMutex); // let go of data
- }
- else // unable to get mutex
- { return(NOTSECURE);
- }
- }
-
- return(SUCCESS); // success
- }
- else // new failed
- { return(NOCREATELINK);
- }
- }
-
-
- short Getlink(short LinkID,short option)
- { // option WHOLELIST = the whole list once
- // option GETID = get ID
- short result = 0;
-
- switch (option)
- { case WHOLELIST:
- { int loop;
- int check = 0;
-
- // cycle list of links and update each
- for (loop = 0;loop < g_LinkCount;loop++)
- { if (g_pLinks[loop]->m_InFlag)
- { check = UpdateID(loop);
- if (check)
- { result++;
- }
- }
- }
- break;
- }
-
- case GETID:
- { int loop;
-
- // cycle list of links to find the one specified
- for (loop = 0;loop < g_LinkCount;loop++)
- { if (LinkID == g_pLinks[loop]->m_LinkID && g_pLinks[loop]->m_InFlag) // if this is the link were looking for
- { result = UpdateID(loop);
- }
- }
- break;
- }
-
- default:
- return(INVALIDOPTION);
- break;
-
- }
- return(result);
- }
-
- void StartServer()
- { while (!g_StopLinkRequest)
- { if (WaitEvent(g_hRequestEvents[g_InstanceID])) // wait for requests directed at this instance
- { int loop = 0;
-
- while (loop < g_LinkCount && g_RequestID != g_pLinks[loop]->m_LinkID) // find this ID
- { loop++;
- }
-
- if (loop == g_LinkCount)
- { MessageBox(NULL,"Server data mismatch","Blink Error",MB_OK);
- }
- else
- { if (g_pLinks[loop]->m_DataSize) // if not a string
- { memcpy(&g_DataBlock,g_pLinks[loop]->m_pData,g_pLinks[loop]->m_DataSize); // place data in shared area
- }
- else // is a string
- { g_StringSize = *((short*)((char *)g_pLinks[loop]->m_pData - 2)); // place string size in shared area
- strncpy((char *)&g_DataBlock,(char *)g_pLinks[loop]->m_pData,g_StringSize); // place data in shared area
- }
-
- SetEvent(g_hAnswerEvents[g_RequestInstance]); // reset event to say we answered it
- }
- }
- } // while (!g_StopLinkRequest)
- // thread is shutting down
- SetEvent(g_hShutDown[g_InstanceID]);
- }
-
- void Startlink()
- { if (!g_ListenThread)
- { g_StopLinkRequest = FALSE;
- g_ListenThread = TRUE;
- g_pThread = AfxBeginThread(RUNTIME_CLASS (DialogThread)); // create thread to execute dialog
- }
- }
-
- void Stoplink()
- { if (g_ListenThread)
- { g_StopLinkRequest = TRUE; // set flag to request thread exit
- WaitForSingleObject(g_hShutDown[g_InstanceID],INFINITE); // wait for return signal
- g_ListenThread = FALSE;
- }
- }
-
-
-
- BOOL CBLinkApp::InitInstance()
- { g_hSetupMutex = CreateMutex(NULL,FALSE,"StartupMutex");
- g_hMutex = CreateMutex(NULL,FALSE,"LinkMutex");
- g_hRequestEvents[0] = CreateEvent(NULL,FALSE,FALSE,"RequestEventzero");
- g_hRequestEvents[1] = CreateEvent(NULL,FALSE,FALSE,"RequestEventone");
- g_hRequestEvents[2] = CreateEvent(NULL,FALSE,FALSE,"RequestEventtwo");
- g_hRequestEvents[3] = CreateEvent(NULL,FALSE,FALSE,"RequestEventthree");
- g_hAnswerEvents[0] = CreateEvent(NULL,FALSE,FALSE,"AnswerEventzero");
- g_hAnswerEvents[1] = CreateEvent(NULL,FALSE,FALSE,"AnswerEventone");
- g_hAnswerEvents[2] = CreateEvent(NULL,FALSE,FALSE,"AnswerEventtwo");
- g_hAnswerEvents[3] = CreateEvent(NULL,FALSE,FALSE,"AnswerEventthree");
- g_hShutDown[0] = CreateEvent(NULL,FALSE,FALSE,"ShutDownone");
- g_hShutDown[1] = CreateEvent(NULL,FALSE,FALSE,"ShutDowntwo");
- g_hShutDown[2] = CreateEvent(NULL,FALSE,FALSE,"ShutDownthree");
- g_hShutDown[3] = CreateEvent(NULL,FALSE,FALSE,"ShutDownfour");
-
- if (GetMutex(g_hSetupMutex) && g_NextInstanceID < MAXINSTANCES) // grab setup mutex
- { g_InstanceID = g_NextInstanceID; // get our instance ID
- g_NextInstanceID++; // Update for the next Instance
-
- ReleaseMutex(g_hSetupMutex); // let go of data
- }
- else
- { return(FALSE); // fail to load DLL if fail to get instance ID
- }
-
- return CWinApp::InitInstance();
- }
-
-
-
- int CBLinkApp::ExitInstance()
- { int ServerCheck = 0;
-
- Stoplink();
-
- WaitForSingleObject(g_hMutex,INFINITE);
-
- // cycle ServerList to clean out this instance
- while (ServerCheck < g_ServerCount)
- { if (g_InstanceID == g_ServerList[ServerCheck][1])
- { g_ServerList[ServerCheck][0] = g_ServerList[g_ServerCount - 1][0];
- g_ServerList[ServerCheck][1] = g_ServerList[g_ServerCount - 1][1];
- g_ServerCount--;
- }
- else
- { ServerCheck++;
- }
- }
-
- ReleaseMutex(g_hMutex);
- return CWinApp::ExitInstance();
- }
-