441 lines
12 KiB
C++
441 lines
12 KiB
C++
#include "StdAfx.h"
|
|
#include "ClientManager.h"
|
|
#include "P4BridgeClient.h"
|
|
|
|
extern CRITICAL_SECTION CriticalSection;
|
|
void MyEnterCriticalSection(CRITICAL_SECTION *CriticalSection);
|
|
|
|
ClientManager::ClientManager(void)
|
|
{
|
|
static P4BridgeClient* pFirstItem;
|
|
static P4BridgeClient* pLastItem;
|
|
|
|
defaultUI = NULL;
|
|
ExceptionError = NULL;
|
|
pTextResultsCallbackFn = NULL;
|
|
pInfoResultsCallbackFn = NULL;
|
|
pTaggedOutputCallbackFn = NULL;
|
|
pErrorCallbackFn = NULL;
|
|
pBinaryResultsCallbackFn = NULL;
|
|
pPromptCallbackFn = NULL;
|
|
pResolveCallbackFn = NULL;
|
|
pResolveACallbackFn = NULL;
|
|
}
|
|
|
|
ClientManager::~ClientManager(void)
|
|
{
|
|
if (disposed != 0)
|
|
{
|
|
return;
|
|
}
|
|
// defaultUI is deleted when the uderlying list is deleted
|
|
//if (defaultUI != NULL)
|
|
//{
|
|
// delete defaultUI;
|
|
// defaultUI = NULL;
|
|
//}
|
|
}
|
|
|
|
P4BridgeClient* ClientManager::CreateNewUI(int cmdId)
|
|
{
|
|
MyEnterCriticalSection(&CriticalSection);
|
|
P4BridgeClient* newClient = new P4BridgeClient(this, cmdId);
|
|
LeaveCriticalSection(&CriticalSection);
|
|
return newClient;
|
|
}
|
|
|
|
P4BridgeClient* ClientManager::GetUI(int cmdId)
|
|
{
|
|
MyEnterCriticalSection(&CriticalSection);
|
|
P4BridgeClient* ui = (P4BridgeClient*) Find(cmdId);
|
|
if (ui == NULL)
|
|
{
|
|
ui = CreateNewUI(cmdId);
|
|
}
|
|
LeaveCriticalSection(&CriticalSection);
|
|
return ui;
|
|
}
|
|
|
|
P4BridgeClient* ClientManager::GetDefaultUI()
|
|
{
|
|
MyEnterCriticalSection(&CriticalSection);
|
|
if (defaultUI == NULL)
|
|
{
|
|
defaultUI = new P4BridgeClient(this,0);
|
|
}
|
|
LeaveCriticalSection(&CriticalSection);
|
|
return defaultUI;
|
|
}
|
|
|
|
void ClientManager::ReleaseUI(int cmdId)
|
|
{
|
|
Remove(cmdId);
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* HandleException
|
|
*
|
|
* Handle any platform exceptions. The Microsoft Structured Exception Handler
|
|
* allows software to catch platform exceptions such as array overrun. The
|
|
* exception is logged, but the application will continue to run.
|
|
*
|
|
******************************************************************************/
|
|
|
|
int ClientManager::HandleException(unsigned int c, struct _EXCEPTION_POINTERS *e)
|
|
{
|
|
unsigned int code = c;
|
|
struct _EXCEPTION_POINTERS *ep = e;
|
|
|
|
// Log the exception
|
|
char * exType = "Unknown";
|
|
|
|
switch (code)
|
|
{
|
|
case EXCEPTION_ACCESS_VIOLATION:
|
|
exType = "EXCEPTION_ACCESS_VIOLATION\r\n";
|
|
break;
|
|
case EXCEPTION_DATATYPE_MISALIGNMENT:
|
|
exType = "EXCEPTION_DATATYPE_MISALIGNMENT\r\n";
|
|
break;
|
|
case EXCEPTION_BREAKPOINT:
|
|
exType = "EXCEPTION_BREAKPOINT\r\n";
|
|
break;
|
|
case EXCEPTION_SINGLE_STEP:
|
|
exType = "EXCEPTION_SINGLE_STEP\r\n";
|
|
break;
|
|
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
|
|
exType = "EXCEPTION_ARRAY_BOUNDS_EXCEEDED\r\n";
|
|
break;
|
|
case EXCEPTION_FLT_DENORMAL_OPERAND:
|
|
exType = "EXCEPTION_FLT_DENORMAL_OPERAND\r\n";
|
|
break;
|
|
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
|
|
exType = "EXCEPTION_FLT_DIVIDE_BY_ZERO\r\n";
|
|
break;
|
|
case EXCEPTION_FLT_INEXACT_RESULT:
|
|
exType = "EXCEPTION_FLT_INEXACT_RESULT\r\n";
|
|
break;
|
|
case EXCEPTION_FLT_INVALID_OPERATION:
|
|
exType = "EXCEPTION_FLT_INVALID_OPERATION\r\n";
|
|
break;
|
|
case EXCEPTION_FLT_OVERFLOW:
|
|
exType = "EXCEPTION_FLT_OVERFLOW\r\n";
|
|
break;
|
|
case EXCEPTION_FLT_STACK_CHECK:
|
|
exType = "EXCEPTION_FLT_STACK_CHECK\r\n";
|
|
break;
|
|
case EXCEPTION_FLT_UNDERFLOW:
|
|
exType = "EXCEPTION_FLT_UNDERFLOW\r\n";
|
|
break;
|
|
case EXCEPTION_INT_DIVIDE_BY_ZERO:
|
|
exType = "EXCEPTION_INT_DIVIDE_BY_ZERO\r\n";
|
|
break;
|
|
case EXCEPTION_INT_OVERFLOW:
|
|
exType = "EXCEPTION_INT_OVERFLOW\r\n";
|
|
break;
|
|
case EXCEPTION_PRIV_INSTRUCTION:
|
|
exType = "EXCEPTION_PRIV_INSTRUCTION\r\n";
|
|
break;
|
|
case EXCEPTION_IN_PAGE_ERROR:
|
|
exType = "EXCEPTION_IN_PAGE_ERROR\r\n";
|
|
break;
|
|
case EXCEPTION_ILLEGAL_INSTRUCTION:
|
|
exType = "EXCEPTION_ILLEGAL_INSTRUCTION\r\n";
|
|
break;
|
|
case EXCEPTION_NONCONTINUABLE_EXCEPTION:
|
|
exType = "EXCEPTION_NONCONTINUABLE_EXCEPTION\r\n";
|
|
break;
|
|
case EXCEPTION_STACK_OVERFLOW:
|
|
exType = "EXCEPTION_STACK_OVERFLOW\r\n";
|
|
break;
|
|
case EXCEPTION_INVALID_DISPOSITION:
|
|
exType = "EXCEPTION_INVALID_DISPOSITION\r\n";
|
|
break;
|
|
case EXCEPTION_GUARD_PAGE:
|
|
exType = "EXCEPTION_GUARD_PAGE\r\n";
|
|
break;
|
|
case EXCEPTION_INVALID_HANDLE:
|
|
exType = "EXCEPTION_INVALID_HANDLE\r\n";
|
|
break;
|
|
//case EXCEPTION_POSSIBLE_DEADLOCK:
|
|
// exType = "EXCEPTION_POSSIBLE_DEADLOCK\r\n");
|
|
// break;
|
|
default:
|
|
printf("UNKOWN EXCEPTION\r\n");
|
|
break;
|
|
}
|
|
if (ExceptionError != NULL)
|
|
delete ExceptionError;
|
|
|
|
ExceptionError = new StrBuf();
|
|
|
|
ExceptionError->Append("Exception Detected in callback function: ");
|
|
ExceptionError->Append(exType);
|
|
|
|
return EXCEPTION_EXECUTE_HANDLER;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* CallTextResultsCallbackFn
|
|
*
|
|
* Simple wrapper to call the callback function (if it has been set) within a
|
|
* SEH __try block to catch any platform exception. SEH __try blocks must
|
|
* be contained in simple functions or you will get Compiler Error C2712,
|
|
* "cannot use __try in functions that require object unwinding"
|
|
*
|
|
******************************************************************************/
|
|
|
|
void ClientManager::CallTextResultsCallbackFn(int cmdId, const char *data)
|
|
{
|
|
__try
|
|
{
|
|
if (pTextResultsCallbackFn != NULL)
|
|
{
|
|
(*pTextResultsCallbackFn)( cmdId, data );
|
|
}
|
|
} __except (HandleException(GetExceptionCode(), GetExceptionInformation()))
|
|
{
|
|
this->GetUI(cmdId)->HandleError( E_FATAL, 0, ExceptionError->Text());
|
|
}
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* CallInfoResultsCallbackFn
|
|
*
|
|
* Simple wrapper to call the callback function (if it has been set) within a
|
|
* SEH __try block to catch any platform exception. SEH __try blocks must
|
|
* be contained in simple functions or you will get Compiler Error C2712,
|
|
* "cannot use __try in functions that require object unwinding"
|
|
*
|
|
******************************************************************************/
|
|
|
|
void ClientManager::CallInfoResultsCallbackFn( int cmdId, char level, const char *data )
|
|
{
|
|
__try
|
|
{
|
|
if (pInfoResultsCallbackFn != NULL)
|
|
{
|
|
int nlevel = (int)(level - '0');
|
|
(*pInfoResultsCallbackFn)( cmdId, nlevel, data );
|
|
}
|
|
}
|
|
__except (HandleException(GetExceptionCode(), GetExceptionInformation()))
|
|
{
|
|
GetUI(cmdId)->HandleError( E_FATAL, 0, ExceptionError->Text());
|
|
}
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* CallTaggedOutputCallbackFn
|
|
*
|
|
* Simple wrapper to call the callback function (if it has been set) within a
|
|
* SEH __try block to catch any platform exception. SEH __try blocks must
|
|
* be contained in simple functions or you will get Compiler Error C2712,
|
|
* "cannot use __try in functions that require object unwinding"
|
|
*
|
|
******************************************************************************/
|
|
|
|
void ClientManager::CallTaggedOutputCallbackFn( int cmdId, int objId, const char *pKey, const char * pVal )
|
|
{
|
|
__try
|
|
{
|
|
if (pTaggedOutputCallbackFn != NULL)
|
|
{
|
|
(*pTaggedOutputCallbackFn)( cmdId, objId, pKey, pVal );
|
|
}
|
|
}
|
|
__except (HandleException(GetExceptionCode(), GetExceptionInformation()))
|
|
{
|
|
GetUI(cmdId)->HandleError( E_FATAL, 0, ExceptionError->Text());
|
|
}
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* CallErrorCallbackFn
|
|
*
|
|
* Simple wrapper to call the callback function (if it has been set) within a
|
|
* SEH __try block to catch any platform exception. SEH __try blocks must
|
|
* be contained in simple functions or you will get Compiler Error C2712,
|
|
* "cannot use __try in functions that require object unwinding"
|
|
*
|
|
******************************************************************************/
|
|
|
|
void ClientManager::CallErrorCallbackFn( int cmdId, int severity, int errorId, const char * errMsg )
|
|
{
|
|
__try
|
|
{
|
|
if (pErrorCallbackFn != NULL)
|
|
{
|
|
(*pErrorCallbackFn)( cmdId, severity, errorId, errMsg );
|
|
}
|
|
}
|
|
__except (HandleException(GetExceptionCode(), GetExceptionInformation()))
|
|
{
|
|
// could cause infinite recursion if we keep producing errors
|
|
// when reporting errors
|
|
pErrorCallbackFn = NULL;
|
|
GetUI(cmdId)->HandleError( E_FATAL, 0, ExceptionError->Text());
|
|
}
|
|
}
|
|
/*******************************************************************************
|
|
*
|
|
* CallErrorCallbackFn
|
|
*
|
|
* Simple wrapper to call the callback function (if it has been set) within a
|
|
* SEH __try block to catch any platform exception. SEH __try blocks must
|
|
* be contained in simple functions or you will get Compiler Error C2712,
|
|
* "cannot use __try in functions that require object unwinding"
|
|
*
|
|
******************************************************************************/
|
|
|
|
void ClientManager::CallBinaryResultsCallbackFn( int cmdId, void * data, int length )
|
|
{
|
|
__try
|
|
{
|
|
if (pBinaryResultsCallbackFn)
|
|
(*pBinaryResultsCallbackFn)( cmdId, (void *) data, length );
|
|
}
|
|
__except (HandleException(GetExceptionCode(), GetExceptionInformation()))
|
|
{
|
|
GetUI(cmdId)->HandleError( E_FATAL, 0, ExceptionError->Text());
|
|
}
|
|
}
|
|
// Set the call back function to receive the tagged output
|
|
void ClientManager::SetTaggedOutputCallbackFn(IntTextTextCallbackFn* pNew)
|
|
{
|
|
pTaggedOutputCallbackFn = pNew;
|
|
}
|
|
|
|
// Set the call back function to receive the error output
|
|
void ClientManager::SetErrorCallbackFn(IntIntIntTextCallbackFn* pNew)
|
|
{
|
|
pErrorCallbackFn = pNew;
|
|
}
|
|
|
|
void ClientManager::Prompt( int cmdId, const StrPtr &msg, StrBuf &rsp,
|
|
int noEcho, Error *e )
|
|
{
|
|
__try
|
|
{
|
|
if (pPromptCallbackFn)
|
|
{
|
|
char response[1024];
|
|
|
|
(*pPromptCallbackFn)( cmdId, msg.Text(), response, sizeof(response), noEcho);
|
|
|
|
rsp.Set(response);
|
|
}
|
|
} __except (HandleException(GetExceptionCode(), GetExceptionInformation()))
|
|
{
|
|
GetUI(cmdId)->HandleError( E_FATAL, 0, ExceptionError->Text());
|
|
}
|
|
}
|
|
|
|
void ClientManager::SetPromptCallbackFn( PromptCallbackFn * pNew)
|
|
{
|
|
pPromptCallbackFn = pNew;
|
|
}
|
|
|
|
// Set the call back function to receive the information output
|
|
void ClientManager::SetInfoResultsCallbackFn(IntIntTextCallbackFn* pNew)
|
|
{
|
|
pInfoResultsCallbackFn = pNew;
|
|
}
|
|
|
|
// Set the call back function to receive the text output
|
|
void ClientManager::SetTextResultsCallbackFn(TextCallbackFn* pNew)
|
|
{
|
|
pTextResultsCallbackFn = pNew;
|
|
}
|
|
|
|
// Set the call back function to receive the binary output
|
|
void ClientManager::SetBinaryResultsCallbackFn(BinaryCallbackFn* pNew)
|
|
{
|
|
pBinaryResultsCallbackFn = pNew;
|
|
}
|
|
|
|
// Callbacks for handling interactive resolve
|
|
int ClientManager::Resolve( int cmdId, ClientMerge *m, Error *e )
|
|
{
|
|
if (pResolveCallbackFn == NULL)
|
|
{
|
|
return CMS_SKIP;
|
|
}
|
|
P4ClientMerge *merger = new P4ClientMerge(m);
|
|
int result = -1;
|
|
|
|
result = Resolve_int( cmdId, merger );
|
|
|
|
delete merger;
|
|
|
|
if (result == -1)
|
|
{
|
|
return GetUI(cmdId)->ClientUser::Resolve( m, e );
|
|
}
|
|
return result;
|
|
}
|
|
|
|
int ClientManager::Resolve( int cmdId, ClientResolveA *r, int preview, Error *e )
|
|
{
|
|
if (pResolveACallbackFn == NULL)
|
|
{
|
|
return CMS_SKIP;
|
|
}
|
|
|
|
P4ClientResolve *resolver = new P4ClientResolve(r, isUnicode);
|
|
int result = -1;
|
|
|
|
result = Resolve_int( cmdId, resolver, preview, e);
|
|
|
|
delete resolver;
|
|
|
|
if (result == -1)
|
|
{
|
|
return CMS_SKIP;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void ClientManager::SetResolveCallbackFn(ResolveCallbackFn * pNew)
|
|
{
|
|
pResolveCallbackFn = pNew;
|
|
}
|
|
|
|
void ClientManager::SetResolveACallbackFn(ResolveACallbackFn * pNew)
|
|
{
|
|
pResolveACallbackFn = pNew;
|
|
}
|
|
|
|
int ClientManager::Resolve_int( int cmdId, P4ClientMerge *merger)
|
|
{
|
|
int result = -1;
|
|
__try
|
|
{
|
|
result = (*pResolveCallbackFn)(cmdId, merger);
|
|
}
|
|
__except (HandleException(GetExceptionCode(), GetExceptionInformation()))
|
|
{
|
|
GetUI(cmdId)->HandleError( E_FATAL, 0, ExceptionError->Text());
|
|
}
|
|
return result;
|
|
}
|
|
|
|
int ClientManager::Resolve_int( int cmdId, P4ClientResolve *resolver, int preview, Error *e)
|
|
{
|
|
int result = -1;
|
|
__try
|
|
{
|
|
result = (*pResolveACallbackFn)(cmdId, resolver, preview);
|
|
}
|
|
__except (HandleException(GetExceptionCode(), GetExceptionInformation()))
|
|
{
|
|
GetUI(cmdId)->HandleError( E_FATAL, 0, ExceptionError->Text());
|
|
}
|
|
return result;
|
|
}
|