#include "StdAfx.h" #include "ClientManager.h" #include "P4BridgeClient.h" #ifdef OS_NT extern CRITICAL_SECTION CriticalSection; void MyEnterCriticalSection(CRITICAL_SECTION *CriticalSection); #endif 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) { #ifdef OS_NT MyEnterCriticalSection(&CriticalSection); #endif P4BridgeClient* newClient = new P4BridgeClient(this, cmdId); #ifdef OS_NT LeaveCriticalSection(&CriticalSection); #endif return newClient; } P4BridgeClient* ClientManager::GetUI(int cmdId) { #ifdef OS_NT MyEnterCriticalSection(&CriticalSection); #endif P4BridgeClient* ui = (P4BridgeClient*) Find(cmdId); if (ui == NULL) { ui = CreateNewUI(cmdId); } #ifdef OS_NT LeaveCriticalSection(&CriticalSection); #endif return ui; } P4BridgeClient* ClientManager::GetDefaultUI() { #ifdef OS_NT MyEnterCriticalSection(&CriticalSection); #endif if (defaultUI == NULL) { defaultUI = new P4BridgeClient(this,0); } #ifdef OS_NT LeaveCriticalSection(&CriticalSection); #endif 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; }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#1 | 19640 | Liz Lam | "Forking branch Main of perforce-software-p4connect to liz_lam-p4connect." | ||
//guest/perforce_software/p4connect/main/src/P4Bridge/p4bridge/ClientManager.cpp | |||||
#1 | 16209 | Norman Morse | Move entire source tree into "main" branch so workshop code will act correctly. | ||
//guest/perforce_software/p4connect/src/P4Bridge/p4bridge/ClientManager.cpp | |||||
#2 | 12135 | Norman Morse |
Integrate dev branch changes into main. This code is the basiis of the 2.7 BETA release which provides Unity 5 compatibility |
||
#1 | 10940 | Norman Morse |
Inital Workshop release of P4Connect. Released under BSD-2 license |