testtoolsconn/stat/desktop/source/lib/src/statengine.cpp
changeset 0 3da2a79470a7
equal deleted inserted replaced
-1:000000000000 0:3da2a79470a7
       
     1 /*
       
     2 * Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 
       
    21 #include "stdafx.h"
       
    22 #include "STATEngine.h"
       
    23 #include "STATCommon.h"
       
    24 #include "INI.h"
       
    25 
       
    26 #include <string>
       
    27 
       
    28 //----------------------------------------------------------------------------
       
    29 // Constructor
       
    30 CSTATEngine::CSTATEngine()
       
    31 : pImageVerify(NULL), pConverter(NULL), pComms(NULL), pDecoder(NULL), pLog(NULL),
       
    32   minimumdelay(100), maximumdelay(30000), eStopProcessing(STAT_RUN), iCurrentCommand(0), bMultithreaded(false),
       
    33   eConnectType(SymbianInvalid), pDeviceInfo(NULL), iDeviceCode(0), iMaxTimeLimit(STAT_MAXTIME), dataSocket(NULL), settingSocket(true), iTEFSharedData(NULL)
       
    34 {	
       
    35 	memset(&szAddress, 0, sizeof(szAddress));
       
    36 	statIniFile.SetIniFileName(STAT_INI_NAME);
       
    37 }
       
    38 
       
    39 
       
    40 //----------------------------------------------------------------------------
       
    41 // Destructor
       
    42 CSTATEngine::~CSTATEngine()
       
    43 {
       
    44 	Release();
       
    45 }
       
    46 
       
    47 
       
    48 //----------------------------------------------------------------------------
       
    49 // Set things up
       
    50 int
       
    51 CSTATEngine::Initialise(const STATCONNECTTYPE eConnect, const char *pAddress)
       
    52 {
       
    53 	iDelay = minimumdelay;
       
    54 
       
    55 
       
    56 
       
    57 
       
    58 	// logging - should be the first to be created for all other classes that depend on it
       
    59 	pLog = new CSTATLogFile;
       
    60  	if (!pLog)
       
    61  		return E_OUTOFMEM;
       
    62 
       
    63 	int ret = SetScreenshotDefaultDirectory();
       
    64 	if (ret != ITS_OK)
       
    65 		return ret;
       
    66 
       
    67 	// image verification
       
    68  	pImageVerify = new CSTATImageVerify(pLog);
       
    69  	if (!pImageVerify)
       
    70  		return E_OUTOFMEM;
       
    71 
       
    72 	// bitmap conversion
       
    73 	pConverter = new CSTATDataFormatConverter(pLog);
       
    74  	if (!pConverter)
       
    75  		return E_OUTOFMEM;
       
    76 
       
    77 	// script decoder
       
    78 	pDecoder = new CSTATScriptDecoder(pLog);
       
    79  	if (!pDecoder)
       
    80  		return E_OUTOFMEM;
       
    81 
       
    82 	// communications
       
    83 	pComms = new STATComms();
       
    84  	if (!pComms)
       
    85  		return E_OUTOFMEM;
       
    86 	else
       
    87 	{
       
    88 		EnterCriticalSection(&CriticalSection);
       
    89 
       
    90 		ret = pComms->SetTransport(eConnect);
       
    91 		if (ret == ITS_OK)
       
    92 		{
       
    93 			ret = pComms->Initialise();
       
    94 
       
    95 			if (ret == ITS_OK)
       
    96 				ret = pComms->Connect(pAddress);
       
    97 
       
    98 			if (ret == ITS_OK)
       
    99 			{
       
   100 				strcpy(szAddress, pAddress);	// save port in case of restart after error
       
   101 				eConnectType = eConnect;
       
   102 			}
       
   103 		}
       
   104 
       
   105 		LeaveCriticalSection(&CriticalSection);
       
   106 	}
       
   107 	return ret;
       
   108 }
       
   109 
       
   110 
       
   111 
       
   112 //----------------------------------------------------------------------------
       
   113 // Release resources
       
   114 int
       
   115 CSTATEngine::Release(void)
       
   116 {
       
   117 	if (pImageVerify)
       
   118 	{
       
   119 		delete pImageVerify;
       
   120 		pImageVerify = NULL;
       
   121 	}
       
   122 
       
   123 	if (pConverter)
       
   124 	{
       
   125 		delete pConverter;
       
   126 		pConverter = NULL;
       
   127 	}
       
   128 
       
   129 	if (pDecoder)
       
   130 	{
       
   131 		delete pDecoder;
       
   132 		pDecoder = NULL;
       
   133 	}
       
   134 
       
   135 	if (pDeviceInfo)
       
   136 	{
       
   137 		delete [] pDeviceInfo;
       
   138 		pDeviceInfo = NULL;
       
   139 	}
       
   140 
       
   141 	if (iTEFSharedData)
       
   142 	{
       
   143 		delete [] iTEFSharedData;
       
   144 		iTEFSharedData = NULL;
       
   145 	}
       
   146 	
       
   147 	EnterCriticalSection(&CriticalSection);
       
   148 
       
   149 	if (pComms)
       
   150 	{
       
   151 		delete pComms;
       
   152 		pComms = NULL;
       
   153 	}
       
   154 
       
   155 	// release this one last in case other objects are using it...
       
   156 	if (pLog)
       
   157 	{
       
   158 		pLog->CloseLogFile();
       
   159 		delete pLog;
       
   160 		pLog = NULL;
       
   161 	}
       
   162 
       
   163 	LeaveCriticalSection(&CriticalSection);
       
   164 	return ITS_OK;
       
   165 }
       
   166 
       
   167 
       
   168 //----------------------------------------------------------------------------
       
   169 // Sets up log file
       
   170 int
       
   171 CSTATEngine::SetLogging(const CString& logfilename, const char* prefix, bool append, bool bMessages, bool bFile,
       
   172 	MessageReporter *const aMessageReporter)
       
   173 {
       
   174 	EnterCriticalSection(&CriticalSection);
       
   175 	//set default logging path
       
   176 	CString defaultDirectory=STAT_LOGFILEPATH_VALUE;
       
   177 	//read from inifile if entry exists
       
   178 	if(statIniFile.SectionExists(ST_TEST_KEY) )
       
   179 	{
       
   180 		CString setting;
       
   181 		setting.Empty();
       
   182 		setting=statIniFile.GetKeyValue(ST_LOGFILEPATH,ST_TEST_KEY);
       
   183 		if(!setting.IsEmpty())
       
   184 			defaultDirectory = setting;
       
   185 	}
       
   186 	int ret = pLog->CreateLogFile(logfilename,defaultDirectory, prefix, append, bMessages, bFile);
       
   187 
       
   188 	pLog->SetMessageReporter(aMessageReporter);
       
   189 
       
   190 	// in case our transport was initialised before logging was
       
   191 	// display the initialisation message if there is one
       
   192 	if (ret == LOG_FILE_OK)
       
   193 		Message(pComms->Error());
       
   194 
       
   195 	LeaveCriticalSection(&CriticalSection);
       
   196 	return ret;
       
   197 }
       
   198 
       
   199 
       
   200 //----------------------------------------------------------------------------
       
   201 // Sets up log file
       
   202 void
       
   203 CSTATEngine::SetCommandDelay(int iMillisecondDelay)
       
   204 {
       
   205 	iDelay = iMillisecondDelay;
       
   206 
       
   207 	// set some limits
       
   208 	if (iDelay < 100)
       
   209 		iDelay = minimumdelay;
       
   210 
       
   211 	if (iDelay > 30000)
       
   212 		iDelay = maximumdelay;
       
   213 }
       
   214 
       
   215 
       
   216 //----------------------------------------------------------------------------
       
   217 // Open, read and count the amount of commands on this script
       
   218 int
       
   219 CSTATEngine::GetCommandCount(CString file, int *pCount)
       
   220 {
       
   221 	EnterCriticalSection(&CriticalSection);
       
   222 
       
   223 	int ret = pDecoder->Initialise(file, true);
       
   224 	if (ret != ITS_OK)
       
   225 		ret = pDecoder->Initialise(file, false);
       
   226 
       
   227 	if (ret == ITS_OK)
       
   228 	{
       
   229 		CSTATScriptCommand *pSendCommand;
       
   230 		int iCount = 0;
       
   231 		
       
   232 		// get a command from the script
       
   233 		while (pDecoder->GetNextCommand(&pSendCommand) && ret == ITS_OK)
       
   234 		{
       
   235 			iCount++;
       
   236 			if (pSendCommand->cCommandID == STAT_END)
       
   237 				break;
       
   238 		}
       
   239 
       
   240 		// set the count
       
   241 		if (ret == ITS_OK)
       
   242 			(*pCount) = iCount;
       
   243 	}
       
   244 
       
   245 	pDecoder->Release();
       
   246 
       
   247 	LeaveCriticalSection(&CriticalSection);
       
   248 	return ret;
       
   249 }
       
   250 
       
   251 
       
   252 //----------------------------------------------------------------------------
       
   253 // Open and read a script file's contents
       
   254 int
       
   255 CSTATEngine::OpenScriptFile(CString file, bool bIsFile)
       
   256 {
       
   257 	EnterCriticalSection(&CriticalSection);
       
   258 
       
   259 	int ret = pDecoder->Initialise(file, bIsFile);
       
   260 
       
   261 	LeaveCriticalSection(&CriticalSection);
       
   262 	return ret;
       
   263 }
       
   264 
       
   265 
       
   266 //----------------------------------------------------------------------------
       
   267 // Execute a script file
       
   268 int
       
   269 CSTATEngine::RunScript(ScriptProgressMonitor *const monitor)
       
   270 {
       
   271 	int ret = ITS_OK;
       
   272 	iCurrentCommand = 0;
       
   273 	eStopProcessing = STAT_RUN;
       
   274 	iDeviceCode = 0;
       
   275 
       
   276 	// anything smaller can cause problems and doesn't make sense anyway!
       
   277 	if (iMaxTimeLimit < 1000)
       
   278 		iMaxTimeLimit = 1000;
       
   279 
       
   280 	// pointers to our command structures
       
   281 	CSTATScriptCommand *pSendCommand;
       
   282 	CSTATScriptCommand *pRecvCommand;
       
   283 
       
   284 	char lastCommand = NULL;
       
   285 
       
   286 	receivedData.Empty( );
       
   287 	
       
   288 	
       
   289 
       
   290 	// get a command from the script
       
   291 	while (pDecoder->GetNextCommand(&pSendCommand) && ret == ITS_OK)
       
   292 	{
       
   293 		iCurrentCommand++;
       
   294 
       
   295 		if (StopProcessing())
       
   296 		{
       
   297 			pComms->Send(STAT_RESYNCID);
       
   298 			ret = E_USERCANCEL;
       
   299 			break;
       
   300 		}
       
   301 
       
   302 		if (lastCommand == STAT_REBOOT)
       
   303 		{
       
   304 			ret = ITS_OK;
       
   305 			break;
       
   306 		}
       
   307 
       
   308 		switch(pSendCommand->cCommandID)
       
   309 		{
       
   310 			case 'P':
       
   311 				Message(pSendCommand->Command());
       
   312 				Sleep(atol(pSendCommand->Command()));
       
   313 				break;
       
   314 			case '/':
       
   315 				Message(pSendCommand->Command());
       
   316 				break;
       
   317 			case '#':
       
   318 				{
       
   319 					Message(pSendCommand->Command());
       
   320 					cScreenshotDirectory = pSendCommand->Command();
       
   321 					if(cScreenshotDirectory.Right(1) != _T("\\"))
       
   322 						cScreenshotDirectory += _T("\\");
       
   323 					CreateAllDirectories(cScreenshotDirectory);
       
   324 				}
       
   325 				break;
       
   326 			
       
   327 			default:
       
   328 				{
       
   329 
       
   330 					// send the command and retrieve a response
       
   331 					int iResyncErrors = 0;
       
   332 					while ((ret = SendCommand(pSendCommand, &pRecvCommand)) == E_RESYNCCOMMAND)
       
   333 					{
       
   334 						Sleep(STAT_RETRYDELAY);
       
   335 						iResyncErrors++;
       
   336 						if (iResyncErrors > STAT_MAXERRORS)
       
   337 						{
       
   338 							Message("Too many resync errors - stopping");
       
   339 							ret = E_COMMANDFAILED;
       
   340 							break;
       
   341 						}
       
   342 						
       
   343 					}
       
   344 
       
   345 					if (ret == ITS_OK)
       
   346 					{
       
   347 						// perform special operations for these commands
       
   348 						switch(pSendCommand->cCommandID)
       
   349 						{
       
   350 							case 'D':
       
   351 								StoreData(pRecvCommand->Command(), pRecvCommand->Length(), pDeviceInfo);
       
   352 								AppendCommandToSTATLog("*** DEVICE INFORMATION ***", pRecvCommand->Command(), pRecvCommand->Length());
       
   353 								break;
       
   354 							case 'S':
       
   355 							{
       
   356 								// convert and save the data returned in the response
       
   357 								CString image = pSendCommand->Command();
       
   358 								ret = ConvertAndSaveScreeenshot(image, pRecvCommand->Command(), pRecvCommand->Length());
       
   359 
       
   360 								// imave verification
       
   361 								if (ret == ITS_OK)
       
   362 								{
       
   363 									if (pImageVerify->IsActive() && pConverter->bWriteToFile)
       
   364 									{
       
   365 										ret = pImageVerify->VerifyImage(image);
       
   366 										if (ret == VERIFICATION_PASS)
       
   367 											ret = ITS_OK;
       
   368 									}
       
   369 								}
       
   370 								break;
       
   371 							}
       
   372 						
       
   373 							case 'T':
       
   374 							{
       
   375 								
       
   376 								if(dataSocket==NULL)
       
   377 								{
       
   378 
       
   379 									// filename has been sent, now send the file itself
       
   380 									CSTATScriptCommand oSendCommand;
       
   381 									oSendCommand.cCommandID = pRecvCommand->cCommandID;
       
   382 									
       
   383 										// read and send the file contents
       
   384 									if ((ret = ReadTransferFile(pSendCommand->Command(), &oSendCommand)) == ITS_OK)
       
   385 									{
       
   386 										int iResyncErrors = 0;
       
   387 										while ((ret = SendCommand(&oSendCommand, &pRecvCommand)) == E_RESYNCCOMMAND)
       
   388 										{
       
   389 											Sleep(STAT_RETRYDELAY);
       
   390 											iResyncErrors++;
       
   391 											if (iResyncErrors > STAT_MAXERRORS)
       
   392 											{
       
   393 												Message("Too many resync errors - stopping");
       
   394 												ret = E_COMMANDFAILED;
       
   395 												break;
       
   396 											}
       
   397 										}
       
   398 									}
       
   399 									
       
   400 								}
       
   401 								else
       
   402 								{
       
   403 									//release the socket
       
   404 									ret = ReleaseSocket();
       
   405 									
       
   406 								}
       
   407 								
       
   408 
       
   409 								break;
       
   410 							}
       
   411 							case 'R':
       
   412 							case 'X':
       
   413 							{	
       
   414 								if(dataSocket==NULL)
       
   415 								{
       
   416 									// save the file contents
       
   417 									ret = SaveTransferFile(pSendCommand->Command(), pRecvCommand->Command(), pRecvCommand->Length());
       
   418 								}
       
   419 								else
       
   420 								{
       
   421 									//release the socket
       
   422 									ret = ReleaseSocket();
       
   423 								}
       
   424 								break;
       
   425 							}
       
   426 							case 'G':
       
   427 							{
       
   428 								// upload the device log file and write to STAT log file
       
   429 								AppendCommandToSTATLog("*** DEVICE LOG ***", pRecvCommand->Command(), pRecvCommand->Length());
       
   430 								break;
       
   431 							}
       
   432 							case STAT_REFRESH:
       
   433 							case STAT_END:
       
   434 							{
       
   435 								ret = END_SCRIPT;
       
   436 								break;
       
   437 							}
       
   438 							case 'N':
       
   439 							{
       
   440 								// Retrieve the TEF shared data
       
   441 								StoreData(pRecvCommand->Command(), pRecvCommand->Length(), iTEFSharedData);
       
   442 								AppendCommandToSTATLog("*** RETRIEVE TEF SHARED DATA ***", pRecvCommand->Command(), pRecvCommand->Length());
       
   443 							}
       
   444 							break;
       
   445 							default:
       
   446 							{
       
   447 								Sleep(iDelay);
       
   448 								break;
       
   449 							}
       
   450 						}
       
   451 					}
       
   452 
       
   453 					if (ret == ITS_OK)
       
   454 					{
       
   455 						// Data received from certain of the commands is stored
       
   456 						// for retreival later.
       
   457 						switch(pSendCommand->cCommandID)
       
   458 						{
       
   459 							case 'W':
       
   460 							case 'V':
       
   461 							//execute returns pid
       
   462 							case 'J':
       
   463 							//poll returns 0 1
       
   464 							case '3':
       
   465 								receivedData += oRecvCommand.Command();
       
   466 								break;
       
   467 							default:
       
   468 								break;
       
   469 						}
       
   470 					}
       
   471 				}
       
   472 				break;
       
   473 		}
       
   474 
       
   475 		lastCommand = pSendCommand->cCommandID;
       
   476 
       
   477 		if(monitor)
       
   478 		{
       
   479 			monitor->OnCompleteCommand( iCurrentCommand );
       
   480 		}
       
   481 	}
       
   482 
       
   483 	pDecoder->Release();
       
   484 
       
   485 	return ret;
       
   486 }
       
   487 
       
   488 
       
   489 //////////////////////////////////////////////////////////////////////////////////////////
       
   490 // Converts a char * to it's Unicode equivalent
       
   491 //
       
   492 LPTSTR
       
   493 CSTATEngine::ToUnicode(const char *string)
       
   494 {
       
   495 #ifdef UNICODE
       
   496 	static TCHAR szBuffer[MAX_UNICODE_LEN + 1] = {0};
       
   497 	szBuffer[0] = (TCHAR)0;
       
   498 
       
   499     // Convert to UNICODE.
       
   500     if (!MultiByteToWideChar(CP_ACP,					// conversion type
       
   501 							 0,							// flags
       
   502 							 string,					// source
       
   503 							 -1,						// length
       
   504 							 szBuffer,					// dest
       
   505 							 MAX_UNICODE_LEN))			// length
       
   506     {
       
   507         return _T("Could not convert");
       
   508     }
       
   509     return szBuffer;
       
   510 #else
       
   511 	return (LPTSTR)string;
       
   512 #endif
       
   513 }
       
   514 
       
   515 
       
   516 //////////////////////////////////////////////////////////////////////////////////////////
       
   517 // Converts a Unicode to it's char * equivalent
       
   518 //
       
   519 char *
       
   520 CSTATEngine::ToAnsi(LPCTSTR string)
       
   521 {
       
   522 #ifdef UNICODE
       
   523 	static char szBuffer[MAX_UNICODE_LEN + 1] = {0};
       
   524 	szBuffer[0] = (char)0;
       
   525 
       
   526     // Convert to ANSI.
       
   527     if (!WideCharToMultiByte(CP_ACP,					// conversion type
       
   528 							 0,							// flags
       
   529 							 string,					// source
       
   530 							 -1,						// length
       
   531 							 szBuffer,					// dest
       
   532 							 MAX_UNICODE_LEN,			// length
       
   533 							 NULL,
       
   534 							 NULL ))
       
   535     {
       
   536         return "Could not convert";
       
   537     }
       
   538     return szBuffer;
       
   539 #else
       
   540 	return (char *)string;
       
   541 #endif
       
   542 }
       
   543 
       
   544 
       
   545 //////////////////////////////////////////////////////////////////////////////////////////
       
   546 // PRIVATE METHODS
       
   547 //////////////////////////////////////////////////////////////////////////////////////////
       
   548 
       
   549 //////////////////////////////////////////////////////////////////////////////////////////
       
   550 // sets screenshot image directory
       
   551 int CSTATEngine::SetScreenshotDefaultDirectory(void)
       
   552 {
       
   553 	//Set default logfile path
       
   554 	CString path = ST_LOGFILEPATH_VALUE;
       
   555 	//read from inifile if entry exists
       
   556 	if(statIniFile.SectionExists(ST_TEST_KEY) )
       
   557 	{
       
   558 		CString setting;
       
   559 		setting.Empty();
       
   560 		setting=statIniFile.GetKeyValue(ST_LOGFILEPATH,ST_TEST_KEY);
       
   561 		if(!setting.IsEmpty())
       
   562 			path = setting;
       
   563 	}
       
   564 
       
   565 	
       
   566 	cScreenshotDirectory = path;
       
   567 
       
   568 	// add a backslash
       
   569 	if (cScreenshotDirectory.Right(1) != _T('\\'))
       
   570 		cScreenshotDirectory += _T('\\');
       
   571 
       
   572 	cScreenshotDirectory += _T("Images\\");
       
   573 
       
   574 	return ITS_OK;
       
   575 }
       
   576 
       
   577 
       
   578 //////////////////////////////////////////////////////////////////////////////////////
       
   579 // Execute a complete command
       
   580 //
       
   581 // Sends a command, breaking it up into separate commands if required
       
   582 //
       
   583 // When sending, if larger than our buffer , break it up into correctly sized
       
   584 // pieces and send these.  The first will be an empty one containing the total
       
   585 // size, followed by buffer-sized pieces.  The last will be an empty command.
       
   586 //
       
   587 
       
   588 //////////////////////////////////////////////////////////////////////////////////////
       
   589 int CSTATEngine::SendCommand(CSTATScriptCommand *pSendCommand, CSTATScriptCommand **ppRecvCommand)
       
   590 {
       
   591 	int ret = GENERAL_FAILURE;
       
   592 	CSTATScriptCommand tempCommand;
       
   593 	tempCommand.cCommandID = pSendCommand->cCommandID;
       
   594 
       
   595 
       
   596 	// the first instance of a 'R' or 'T' command, it could set a data socket instead of a file
       
   597 	if(pSendCommand->cCommandID=='T' || pSendCommand->cCommandID=='R')
       
   598 	{
       
   599 		if(dataSocket==NULL && settingSocket && pSendCommand->Command()!=NULL)
       
   600 		{
       
   601 
       
   602 			char *comma = strchr(pSendCommand->Command(),',');
       
   603 			
       
   604 			if(!(comma > pSendCommand->Command() + pSendCommand->Length()))
       
   605 			{
       
   606 	
       
   607 				switch(pSendCommand->cCommandID)
       
   608 				{
       
   609 				case 'R':
       
   610 					{
       
   611 						char *colon = strchr(comma,':');
       
   612 						
       
   613 						if(colon==NULL)
       
   614 							break;
       
   615 	
       
   616 						comma += 1;
       
   617 						std::string ipAdd( comma, colon - comma );
       
   618 						colon += 1;
       
   619 						std::string ipPort( colon );
       
   620 	
       
   621 						ret = SetSocket(ipAdd.c_str() , atoi( ipPort.c_str() ));
       
   622 
       
   623 						if(ret!=ITS_OK)
       
   624 						{
       
   625 							return ret;
       
   626 						}
       
   627 	
       
   628 						break;
       
   629 					}
       
   630 	
       
   631 				case 'T':
       
   632 					{
       
   633 						char *colon = strchr( pSendCommand->Command() , ':' );
       
   634 	
       
   635 						if(colon==NULL)
       
   636 							break;
       
   637 	
       
   638 						std::string ipAdd( pSendCommand->Command() , colon - pSendCommand->Command() );
       
   639 						colon += 1;
       
   640 						
       
   641 						if(comma < colon)
       
   642 							break;
       
   643 	
       
   644 						std::string ipPort( colon , comma - colon );
       
   645 	
       
   646 						ret = SetSocket(ipAdd.c_str() , atoi(ipPort.c_str()));
       
   647 						
       
   648 						if(ret!=ITS_OK)
       
   649 						{
       
   650 							return ret;
       
   651 						}
       
   652 
       
   653 						break;
       
   654 					}
       
   655 				}
       
   656 			}
       
   657 		}
       
   658 
       
   659 		settingSocket=false;
       
   660 	}
       
   661 	
       
   662 	
       
   663 	
       
   664 	// send the first command
       
   665 	if ((ret = SendSingleCommand(pSendCommand, ppRecvCommand)) == ITS_OK)
       
   666 	{
       
   667 		// check our response - if Serial/Infra-red, need to break it down
       
   668 		if (pComms->GetMaxPacketSize() != 0)
       
   669 		{
       
   670 
       
   671 			
       
   672 			// break up the command into buffer-sized chunks
       
   673 			if (pSendCommand->Length() > pComms->GetMaxPacketSize() || (dataSocket!=NULL && pSendCommand->cCommandID=='T'))
       
   674 			{
       
   675 				int i = 0;
       
   676 				unsigned long offset = 0;
       
   677 				unsigned long ulTotalWritten = 0;
       
   678 				unsigned long AmountToWrite = pComms->GetMaxPacketSize();
       
   679 				unsigned long OriginalLength = pSendCommand->Length();
       
   680 				
       
   681 				if(dataSocket==NULL)
       
   682 				{
       
   683 					
       
   684 					int iWrites = pSendCommand->Length() / pComms->GetMaxPacketSize() + 1;
       
   685 
       
   686 					Message("Writing %d bytes of data in %d separate writes...", OriginalLength, iWrites);
       
   687 					for (i=0;i<iWrites;i++)
       
   688 					{
       
   689 						offset = i * pComms->GetMaxPacketSize();
       
   690 
       
   691 						if ((pSendCommand->Length() - offset) < pComms->GetMaxPacketSize())
       
   692 							AmountToWrite = (pSendCommand->Length() - offset);
       
   693 
       
   694 						if (AmountToWrite)
       
   695 						{
       
   696 							//Sleep(100);		// pause a bit for slower machines - probably doesn't need it but it can't hurt...
       
   697 
       
   698 							// now send the command
       
   699 							Message("Writing %d bytes from offset %d", AmountToWrite, offset);
       
   700 							tempCommand.SetData(pSendCommand->Command() + ulTotalWritten, AmountToWrite);
       
   701 							if ((ret = SendSingleCommand(&tempCommand, ppRecvCommand)) == ITS_OK)
       
   702 							{
       
   703 								//Message("%d bytes successfully written", AmountToWrite);
       
   704 							}
       
   705 							else
       
   706 								return ret;
       
   707 
       
   708 							ulTotalWritten += AmountToWrite;
       
   709 						}
       
   710 					}
       
   711 					
       
   712 				}
       
   713 				else
       
   714 				{
       
   715 
       
   716 					//uses socket transmission
       
   717 
       
   718 					char *pData = new char[AmountToWrite];
       
   719 					
       
   720 					tempCommand.ulLength = (unsigned long) -1;
       
   721 					
       
   722 					if((ret = SendSingleCommand(&tempCommand, ppRecvCommand)) != ITS_OK)
       
   723 					{	
       
   724 						delete [] pData;
       
   725 						return ret;
       
   726 					}
       
   727 
       
   728 					while(true){
       
   729 
       
   730 
       
   731 						int AmountToWrite = pComms->GetMaxPacketSize();
       
   732 						
       
   733 						ReadFromSocket(pData, &AmountToWrite );
       
   734 											
       
   735 						if(AmountToWrite>=0)
       
   736 						{
       
   737 							Message("Writing %d bytes", AmountToWrite);
       
   738 							tempCommand.SetData(pData , AmountToWrite);
       
   739 						
       
   740 							if ((ret = SendSingleCommand(&tempCommand, ppRecvCommand)) == ITS_OK)
       
   741 							{
       
   742 							//Message("%d bytes successfully written", AmountToWrite);
       
   743 							}
       
   744 							else
       
   745 							{
       
   746 								settingSocket=true;
       
   747 								delete [] pData;
       
   748 								return ret;
       
   749 							}
       
   750 
       
   751 							ulTotalWritten +=AmountToWrite;
       
   752 						}
       
   753 						else
       
   754 						{
       
   755 							eStopProcessing = STAT_PAUSE;
       
   756 							break;
       
   757 						}
       
   758 						
       
   759 						if(AmountToWrite==0)
       
   760 						{
       
   761 							break;
       
   762 						}
       
   763 						
       
   764 					}
       
   765 
       
   766 					delete [] pData;
       
   767 				
       
   768 				}
       
   769 			
       
   770 				// once completely sent, send an empty command to show that we've finished
       
   771 				
       
   772 				
       
   773 				if(dataSocket == NULL )
       
   774 				{
       
   775 					if (ulTotalWritten == OriginalLength)
       
   776 					{
       
   777 						// send the command that signals the end of our transmission
       
   778 						Message("Sending completion command %c", tempCommand.cCommandID);
       
   779 						tempCommand.SetData(NULL, 0);
       
   780 						if ((ret = SendSingleCommand(&tempCommand, ppRecvCommand)) == ITS_OK)
       
   781 						{
       
   782 							//Message("Completion command successfully written");
       
   783 						}
       
   784 					}
       
   785 					else
       
   786 					{
       
   787 						Message("Incorrect number of bytes written - expected %ld got %ld", ulTotalWritten, OriginalLength);
       
   788 						ret = E_BADNUMBERBYTES;
       
   789 					}
       
   790 				}
       
   791 			}
       
   792 		}
       
   793 	}
       
   794 
       
   795 	if (ret == ITS_OK)
       
   796 	{
       
   797 		// check our response - if Serial/Infra-red, need to break it down
       
   798 		// if < STAT_BUFFERSIZE, nothing more to do
       
   799 		// if not, we need to read in as many times as it takes to
       
   800 		// assemble our complete command response
       
   801 		if (pComms->GetMaxPacketSize() != 0)
       
   802 		{
       
   803 			if (ppRecvCommand && (*ppRecvCommand)->Length() > pComms->GetMaxPacketSize())
       
   804 			{
       
   805 				unsigned long TotalLength = (*ppRecvCommand)->Length();
       
   806 
       
   807 				Message("%s: About to read %d bytes of data", GetConnection(eConnectType), TotalLength);
       
   808 
       
   809 				// allocate memory to hold entire command
       
   810 				char *pTemp = new char [TotalLength];
       
   811 				if (pTemp)
       
   812 				{
       
   813 					unsigned long ulTotalRead = 0;
       
   814 
       
   815 					// empty packets
       
   816 					tempCommand.SetData(NULL, 0);
       
   817 
       
   818 					// now read data until we get an empty packet
       
   819 					while((*ppRecvCommand)->Length())
       
   820 					{
       
   821 						//Sleep(100);		// pause a bit for slower machines - probably doesn't need it but it can't hurt...
       
   822 
       
   823 						//Message("Sending continuation command %c", tempCommand.cCommandID);
       
   824 						if ((ret = SendSingleCommand(&tempCommand, ppRecvCommand)) == ITS_OK)
       
   825 						{
       
   826 							if ((*ppRecvCommand)->Length())
       
   827 							{
       
   828 								Message("%s to offset %d", pComms->Error(), ulTotalRead);
       
   829 								
       
   830 								//copy the data into the buffer
       
   831 								memcpy(pTemp + ulTotalRead, (*ppRecvCommand)->Command(), (*ppRecvCommand)->Length());
       
   832 								
       
   833 								if(dataSocket!=NULL)
       
   834 								{
       
   835 									int bytesSent = (int)(*ppRecvCommand)->Length();
       
   836 								
       
   837 									WriteToSocket((*ppRecvCommand)->Command() , &bytesSent);
       
   838 									
       
   839 									if(bytesSent <= 0)
       
   840 									{
       
   841 										eStopProcessing = STAT_PAUSE;
       
   842 									}
       
   843 								}
       
   844 								
       
   845 								
       
   846 
       
   847 								//increment the pointer to the end of the first chunk received
       
   848 								ulTotalRead += (*ppRecvCommand)->Length();
       
   849 							}
       
   850 						}
       
   851 						else
       
   852 						{
       
   853 							settingSocket=true;
       
   854 							delete [] pTemp;
       
   855 							return ret;
       
   856 						}
       
   857 					}
       
   858 
       
   859 					// make sure we got what we expected
       
   860 					if (ulTotalRead == TotalLength)
       
   861 					{
       
   862 						// set our final response to the complete data transmission
       
   863 						(*ppRecvCommand)->SetData(pTemp, ulTotalRead);
       
   864 						//Message("Received successfully %ld bytes", ulTotalRead);
       
   865 					}
       
   866 					else
       
   867 					{
       
   868 						Message("Incorrect number of bytes read - expected %ld got %ld", ulTotalRead, TotalLength);
       
   869 						ret = E_BADNUMBERBYTES;
       
   870 					}
       
   871 
       
   872 					// finished with it
       
   873 					delete [] pTemp;
       
   874 				}
       
   875 				else
       
   876 				{
       
   877 					Message("Could not allocate %d bytes of memory", TotalLength);
       
   878 					ret = E_OUTOFMEM;
       
   879 				}
       
   880 			}
       
   881 			else if(dataSocket!=NULL && pSendCommand->cCommandID=='R')
       
   882 			{
       
   883 				int bytesSent = (int)(*ppRecvCommand)->Length();
       
   884 				WriteToSocket((*ppRecvCommand)->Command(), &bytesSent);
       
   885 			}
       
   886 		}
       
   887 	}
       
   888 
       
   889 	
       
   890 
       
   891 	return ret;
       
   892 }
       
   893 
       
   894 //////////////////////////////////////////////////////////////////////////////////////
       
   895 // Execute a single command
       
   896 //
       
   897 // Once the command is sent, wait for a response.  If received and of the correct
       
   898 // ID, save the contents (if any) and quit.  If no response, send RESYNC commands
       
   899 // every few seconds to get response from other end.  On receipt of a RESYNC
       
   900 // command, resend the previous command.  After no response for a minute or so, quit.
       
   901 //////////////////////////////////////////////////////////////////////////////////////
       
   902 int CSTATEngine::SendSingleCommand(CSTATScriptCommand *pSendCommand, CSTATScriptCommand **ppRecvCommand)
       
   903 {
       
   904 	int iTotalCommandTime = 0;
       
   905 	int ret = GENERAL_FAILURE;
       
   906 
       
   907 	LogDetails("Send", pSendCommand);
       
   908 
       
   909 	// send the command
       
   910 	EnterCriticalSection(&CriticalSection);
       
   911 	ret = pComms->Send(pSendCommand->cCommandID, pSendCommand->Command(), pSendCommand->Length());
       
   912 	LeaveCriticalSection(&CriticalSection);
       
   913 	if (ret != ITS_OK)
       
   914 	{
       
   915 		Message(pComms->Error());
       
   916 		return ret;
       
   917 	}
       
   918 
       
   919 	// The refresh command will not return anything due to the transport getting restarted.
       
   920 	// So, don't wait for a response.
       
   921 	if( (ret == ITS_OK) && (pSendCommand->cCommandID == STAT_REFRESH || pSendCommand->cCommandID == STAT_REBOOT)  )
       
   922 	{
       
   923 		return ret;
       
   924 	}
       
   925 
       
   926 	// wait for a response
       
   927 	unsigned long ulLength = 0;
       
   928 	char *pData = NULL;
       
   929 	while(iTotalCommandTime < iMaxTimeLimit)
       
   930 	{
       
   931 		if (StopProcessing())
       
   932 		{
       
   933 			pComms->Send(STAT_RESYNCID);
       
   934 			ret = E_USERCANCEL;
       
   935 			break;
       
   936 		}
       
   937 
       
   938 		EnterCriticalSection(&CriticalSection);
       
   939 		ret = pComms->Receive(&oRecvCommand.cCommandID, &pData, &ulLength);
       
   940 		LeaveCriticalSection(&CriticalSection);
       
   941 		
       
   942 		if (ret == ITS_OK)
       
   943 		{
       
   944 			if (oRecvCommand.SetData(pData, ulLength))
       
   945 			{
       
   946 				oRecvCommand.ulLength = ulLength;
       
   947 				*ppRecvCommand = &oRecvCommand;
       
   948 
       
   949 				// invalid response received
       
   950 				if (pSendCommand->cCommandID != oRecvCommand.cCommandID)
       
   951 				{
       
   952 					// need to resync back to start of this command
       
   953 					if (oRecvCommand.cCommandID == STAT_RESYNCID)
       
   954 					{
       
   955 						Message("RESYNC response received - retrying command...");
       
   956 						ret = E_RESYNCCOMMAND;
       
   957 					}
       
   958 					else
       
   959 					{
       
   960 						if (oRecvCommand.cCommandID == STAT_FAILURE)
       
   961 						{
       
   962 							if (oRecvCommand.Command() && oRecvCommand.Length())
       
   963 							{
       
   964 								Message("Command failed with error code %s",
       
   965 										oRecvCommand.Command());
       
   966 								iDeviceCode = atoi(oRecvCommand.Command());
       
   967 							}
       
   968 						}
       
   969 						else
       
   970 							Message("Invalid response received - expected %c received %c",
       
   971 									pSendCommand->cCommandID, oRecvCommand.cCommandID);
       
   972 						ret = GENERAL_FAILURE;
       
   973 					}
       
   974 				}
       
   975 				else
       
   976 					LogDetails("Receive", *ppRecvCommand);
       
   977 			}
       
   978 			else
       
   979 				ret = E_OUTOFMEM;
       
   980 
       
   981 			// at this point we have received something whether it's what we were expecting or not so exit loop
       
   982 			break;
       
   983 		}
       
   984 		else if (ret == NO_DATA_AT_PORT)
       
   985 		{
       
   986 //			Message("Waiting for response");
       
   987 			Sleep(STAT_RETRYDELAY);
       
   988 			iTotalCommandTime += STAT_RETRYDELAY;
       
   989 			ret = E_TOOMUCHTIME;
       
   990 		}
       
   991 		else
       
   992 		{
       
   993 			Message(pComms->Error());
       
   994 			break;
       
   995 		}
       
   996 	}
       
   997 
       
   998 	return ret;
       
   999 }
       
  1000 
       
  1001 
       
  1002 //----------------------------------------------------------------------------
       
  1003 // Write command details to log
       
  1004 void CSTATEngine::LogDetails(const char *prefix, CSTATScriptCommand *pCommand)
       
  1005 {
       
  1006 	if (pCommand->Length() && (pCommand->Length() < MAX_LOG_MSG_LEN) && 
       
  1007 		pCommand->cCommandID != 'D' && pCommand->cCommandID != 'T' && pCommand->cCommandID != 'R' && pCommand->cCommandID != 'X' && pCommand->cCommandID != 'G')
       
  1008 	{
       
  1009 		char szContents[MAX_LOG_MSG_LEN + 1];
       
  1010 		unsigned long actuallen = MAX_LOG_MSG_LEN - 30 - strlen(prefix) - 6;  // max actual message length
       
  1011 		if (pCommand->Length() < actuallen)
       
  1012 			actuallen = pCommand->Length();
       
  1013 
       
  1014 		strncpy(szContents, pCommand->Command(), actuallen);
       
  1015 		*(szContents + actuallen) = (char)0;
       
  1016 		Message("%s: ID: %c Contents: [%s] Length: [%lu]", prefix, pCommand->cCommandID, szContents, pCommand->Length());
       
  1017 	}
       
  1018 	else
       
  1019 		Message("%s: ID: %c Length: [%lu]", prefix, pCommand->cCommandID, pCommand->Length());
       
  1020 }
       
  1021 
       
  1022 
       
  1023 //----------------------------------------------------------------------------
       
  1024 // Read in a file's contents
       
  1025 //
       
  1026 // pFile will contain "pc path,device path" of which we want the 'pc path' part
       
  1027 int CSTATEngine::ReadTransferFile(const char *pFile, CSTATScriptCommand *pCommand)
       
  1028 {
       
  1029 	int ret = E_BADFILENAME;
       
  1030 
       
  1031 	// get the default file location
       
  1032 	CString path = ST_WORKINGPATH_VALUE;
       
  1033 	//read from inifile if entry exists
       
  1034 	if(statIniFile.SectionExists(ST_TEST_KEY) )
       
  1035 	{
       
  1036 		CString setting;
       
  1037 		setting.Empty();
       
  1038 		setting=statIniFile.GetKeyValue(ST_WORKINGPATH,ST_TEST_KEY);
       
  1039 		if(!setting.IsEmpty())
       
  1040 			path = setting;
       
  1041 	}
       
  1042 
       
  1043 	// add a backslash
       
  1044 	if (path.Right(1) != _T('\\'))
       
  1045 		path += _T('\\');
       
  1046 
       
  1047 	// get the name of the file
       
  1048 	CString filename = pFile;
       
  1049 	int index = filename.ReverseFind(_T(','));
       
  1050 	if (index == -1)
       
  1051 		return E_BADFILENAME;
       
  1052 
       
  1053 	// add the name
       
  1054 	path += filename.Left(index);
       
  1055 
       
  1056 	Message("Opening file [%s]", ToAnsi(path));
       
  1057 
       
  1058 	EnterCriticalSection(&CriticalSection);
       
  1059 
       
  1060 	CFile script_file;
       
  1061 	if (script_file.Open(path, CFile::modeRead))
       
  1062 	{
       
  1063 		try
       
  1064 		{
       
  1065 			char *pData = new char [script_file.GetLength()];
       
  1066 			if (pData)
       
  1067 			{
       
  1068 				script_file.Read(pData, script_file.GetLength());
       
  1069 
       
  1070 				if(pCommand->SetData(pData, script_file.GetLength()))
       
  1071 					ret = ITS_OK;
       
  1072 				else
       
  1073 					ret = E_OUTOFMEM;
       
  1074 
       
  1075 				delete [] pData;
       
  1076 			}
       
  1077 			else
       
  1078 				ret = E_OUTOFMEM;
       
  1079 		}
       
  1080 		catch(CFileException *e)
       
  1081 		{
       
  1082 			e->Delete();
       
  1083 			ret = GENERAL_FAILURE;
       
  1084 		}
       
  1085 
       
  1086 		script_file.Abort();
       
  1087 	}
       
  1088 
       
  1089 	LeaveCriticalSection(&CriticalSection);
       
  1090 	return ret;
       
  1091 }
       
  1092 
       
  1093 
       
  1094 
       
  1095 
       
  1096 
       
  1097 
       
  1098 
       
  1099 //----------------------------------------------------------------------------
       
  1100 // Save a data stream to file
       
  1101 //
       
  1102 // pFile will contain "device path,pc folder" of which we want the 'pc folder' part
       
  1103 int CSTATEngine::SaveTransferFile(const char *pFile, char *pContents, unsigned long ulLength)
       
  1104 {
       
  1105 	int ret = E_BADFILENAME;
       
  1106 
       
  1107 	CString path = ST_WORKINGPATH_VALUE;
       
  1108 	//read from inifile if entry exists
       
  1109 	if(statIniFile.SectionExists(ST_TEST_KEY) )
       
  1110 	{
       
  1111 		CString setting;
       
  1112 		setting.Empty();
       
  1113 		setting=statIniFile.GetKeyValue(ST_WORKINGPATH,ST_TEST_KEY);
       
  1114 		if(!setting.IsEmpty())
       
  1115 			path = setting;
       
  1116 	}
       
  1117 	// add a backslash
       
  1118 	if (path.Right(1) != _T('\\'))
       
  1119 		path += _T('\\');
       
  1120 
       
  1121 	// get any additional sub folders
       
  1122 	CString folder = pFile;
       
  1123 	int index = folder.Find(_T(','));
       
  1124 	if (index == -1)
       
  1125 		return E_BADFILENAME;
       
  1126 	// if the comma is the last char there are no folders to add
       
  1127 	if (folder.Right(1) != _T(','))
       
  1128 	{
       
  1129 		path += folder.Mid(index + 1);
       
  1130 
       
  1131 		// add a backslash
       
  1132 		if (path.Right(1) != _T('\\'))
       
  1133 			path += _T('\\');
       
  1134 	}
       
  1135 
       
  1136 	if (bMultithreaded)
       
  1137 	{
       
  1138 		// add a sub-folder for the connection type
       
  1139 		path += GetConnection(eConnectType);
       
  1140 		path += _T(".");
       
  1141 		path += szAddress;
       
  1142 		path += _T('\\');
       
  1143 	}
       
  1144 
       
  1145 	// now extract the filename from the first argument
       
  1146 	CString filename = folder.Left(index);
       
  1147 	index = filename.ReverseFind(_T('\\'));
       
  1148 	if (index == -1)
       
  1149 		path += filename;
       
  1150 	else
       
  1151 		path += filename.Mid(index + 1);
       
  1152 
       
  1153 	Message("Saving file [%s]", ToAnsi(path));
       
  1154 
       
  1155 	ret = SaveTheFile(path, pContents, ulLength);
       
  1156 	if (ret != ITS_OK)
       
  1157 		Message("Error saving [%s] (%d)", ToAnsi(path), GetLastError());
       
  1158 	return ret;
       
  1159 }
       
  1160 
       
  1161 
       
  1162 //----------------------------------------------------------------------------
       
  1163 // Convert and save a screenshot
       
  1164 int CSTATEngine::ConvertAndSaveScreeenshot(CString &file, const char *pContents, const unsigned long ulLength)
       
  1165 {
       
  1166 	int ret = E_BADFILENAME;
       
  1167 
       
  1168 	// clean out any previous mbm files lying around
       
  1169 	if (!RemoveLeftoverMBMFiles())
       
  1170 		return E_SCREENSHOT_LEFTOVERFILES;
       
  1171 
       
  1172 	// get the destination screenshot name
       
  1173 	CString destfile = file;
       
  1174 	if (destfile.IsEmpty())
       
  1175 	{
       
  1176 		// construct a filename from date/time
       
  1177 		char szName[20] = {0};
       
  1178 		time_t curTime;
       
  1179 		time (&curTime);
       
  1180 		strftime (szName, 
       
  1181 					sizeof (szName),
       
  1182 					"%Y%m%d%H%M%S",
       
  1183 					localtime (&curTime));
       
  1184 
       
  1185 		destfile = szName;
       
  1186 	}
       
  1187 
       
  1188 	// get the full name of the source image
       
  1189 	CString SrcPath = cScreenshotDirectory;
       
  1190 
       
  1191 	if (bMultithreaded)
       
  1192 	{
       
  1193 		// add a sub-folder for the connection type
       
  1194 		SrcPath += GetConnection(eConnectType);
       
  1195 		SrcPath += _T(".");
       
  1196 		SrcPath += szAddress;
       
  1197 		SrcPath += _T('\\');
       
  1198 	}
       
  1199 
       
  1200 	// attach the filename
       
  1201 	CString path = SrcPath;
       
  1202 
       
  1203 	path += destfile;
       
  1204 	path += _T(".mbm");
       
  1205 
       
  1206 //	Message("Saving screenshot [%s]", ToAnsi(path));
       
  1207 
       
  1208 	// save bitmap data to file
       
  1209 	if ((ret = SaveTheFile(path, pContents, ulLength)) == ITS_OK)
       
  1210 		ret = pConverter->ConvertScreenShot(SrcPath, SrcPath);
       
  1211 
       
  1212 	// save the full path to the converted image
       
  1213 	if (ret == ITS_OK)
       
  1214 		file = SrcPath;
       
  1215 	return ret;
       
  1216 }
       
  1217 
       
  1218 
       
  1219 //----------------------------------------------------------------------------
       
  1220 // Save data to file
       
  1221 int CSTATEngine::SaveTheFile(CString path, const char *pContents, const unsigned long ulLength)
       
  1222 {
       
  1223 	int ret = E_BADFILENAME;
       
  1224 
       
  1225 	EnterCriticalSection(&CriticalSection);
       
  1226 
       
  1227 	// ensure the path exists
       
  1228 	CreateAllDirectories(path);
       
  1229 
       
  1230 	DeleteFile(path);
       
  1231 
       
  1232 	CFile script_file;
       
  1233 	if (script_file.Open(path, CFile::modeCreate | CFile::modeWrite | CFile::shareDenyWrite))
       
  1234 	{
       
  1235 		try
       
  1236 		{
       
  1237 			// might be a zero-length file
       
  1238 			if (pContents && ulLength)
       
  1239 				script_file.Write(pContents, ulLength);
       
  1240 
       
  1241 			ret = ITS_OK;
       
  1242 		}
       
  1243 		catch(CFileException *e)
       
  1244 		{
       
  1245 			e->Delete();
       
  1246 			ret = GENERAL_FAILURE;
       
  1247 		}
       
  1248 
       
  1249 		script_file.Abort();
       
  1250 	}
       
  1251 
       
  1252 	LeaveCriticalSection(&CriticalSection);
       
  1253 	return ret;
       
  1254 }
       
  1255 
       
  1256 
       
  1257 //----------------------------------------------------------------------------
       
  1258 // Write a message to the log
       
  1259 void CSTATEngine::Message(const char *pMsg, ...)
       
  1260 {
       
  1261 	char szMessage[MAX_LOG_MSG_LEN + 1];
       
  1262 
       
  1263 	if (pMsg)
       
  1264 	{
       
  1265 		memset(&szMessage, 0, sizeof(szMessage));
       
  1266 		va_list pCurrent = (va_list)0;
       
  1267 		va_start (pCurrent, pMsg);
       
  1268 		vsprintf (szMessage, pMsg, pCurrent);
       
  1269 		va_end (pCurrent);
       
  1270 	}
       
  1271 	else
       
  1272 		strcpy(szMessage, "No message associated with this error");
       
  1273 
       
  1274 	EnterCriticalSection(&CriticalSection);
       
  1275 	pLog->Set(szMessage);
       
  1276 	LeaveCriticalSection(&CriticalSection);
       
  1277 }
       
  1278 
       
  1279 //----------------------------------------------------------------------------
       
  1280 // Try to create all directories within a supplied path
       
  1281 void CSTATEngine::CreateAllDirectories(CString &fullpath)
       
  1282 {
       
  1283 	CString path;
       
  1284 	int index = fullpath.Find(_T('\\'));
       
  1285 	while (index != -1)
       
  1286 	{
       
  1287 		path = fullpath.Left(index);
       
  1288 		CreateDirectory(path, NULL);
       
  1289 
       
  1290 		index = fullpath.Find(_T('\\'), index + 1);
       
  1291 	}
       
  1292 }
       
  1293 
       
  1294 //----------------------------------------------------------------------------
       
  1295 // check if we want to quit
       
  1296 bool CSTATEngine::StopProcessing()
       
  1297 {
       
  1298 	// check if instructed to stop processing (will only happen on Desktop version)
       
  1299 	if (eStopProcessing == STAT_PAUSE)
       
  1300 	{
       
  1301 		eStopProcessing = STAT_STOP;
       
  1302 		return true;
       
  1303 	}
       
  1304 
       
  1305 	return false;
       
  1306 }
       
  1307 
       
  1308 //----------------------------------------------------------------------------
       
  1309 //Remove any leftover .mbm files prior to retrieving a screenshot
       
  1310 bool CSTATEngine::RemoveLeftoverMBMFiles()
       
  1311 {
       
  1312 	CFileFind imagefinder;
       
  1313 	CString imagedir = cScreenshotDirectory;
       
  1314 	bool valid = true;
       
  1315 
       
  1316 	// add the search pattern
       
  1317 	if (imagedir.Right(1) != _T('\\'))
       
  1318 		imagedir += _T("\\");
       
  1319 
       
  1320 	// now add a folder for the connection type
       
  1321 	if (bMultithreaded)
       
  1322 	{
       
  1323 		imagedir += GetConnection(eConnectType);
       
  1324 		imagedir += _T(".");
       
  1325 		imagedir += szAddress;
       
  1326 		imagedir += _T('\\');
       
  1327 	}
       
  1328 
       
  1329 	imagedir += _T("*.mbm");
       
  1330 
       
  1331 //	Message("Searching for [%s]", ToAnsi(imagedir));
       
  1332 
       
  1333 	EnterCriticalSection(&CriticalSection);
       
  1334 
       
  1335 	// locate files
       
  1336 	int iLeftFiles = imagefinder.FindFile(imagedir, 0);
       
  1337 	while (iLeftFiles)
       
  1338 	{
       
  1339 		iLeftFiles = imagefinder.FindNextFile();
       
  1340 //		Message("Deleting file [%s]", ToAnsi(imagefinder.GetFilePath()));
       
  1341 
       
  1342 		if (!DeleteFile(imagefinder.GetFilePath()))
       
  1343 		{
       
  1344 			valid = false;
       
  1345 			break;
       
  1346 		}
       
  1347 	}
       
  1348 
       
  1349 	imagefinder.Close();
       
  1350 	LeaveCriticalSection(&CriticalSection);
       
  1351 	return valid;
       
  1352 }
       
  1353 
       
  1354 
       
  1355 //----------------------------------------------------------------------------
       
  1356 // Append the device log to the end of the STAT log
       
  1357 void CSTATEngine::AppendCommandToSTATLog(char *heading, char *log, unsigned long length)
       
  1358 {
       
  1359 	if (length && log)
       
  1360 	{
       
  1361 		EnterCriticalSection(&CriticalSection);
       
  1362 		Message(DOTTED_LINE);
       
  1363 		Message(heading);
       
  1364 
       
  1365 		char *start = log;
       
  1366 		char *eol = log;
       
  1367 		unsigned long count = 0;
       
  1368 
       
  1369 		*(log + length) = (char)0;
       
  1370 
       
  1371 		while (count < length - 1)
       
  1372 		{
       
  1373 			// find the end of the line
       
  1374 			while ((count < length - 1) && (*eol != '\r') && (*eol != '\n'))
       
  1375 			{
       
  1376 				count++;
       
  1377 				eol++;
       
  1378 			}
       
  1379 
       
  1380 			// null it
       
  1381 			if (count < length - 1)
       
  1382 			{
       
  1383 				*eol = (char)0;
       
  1384 				count++;
       
  1385 				eol++;
       
  1386 			}
       
  1387 
       
  1388 			if (start && *start)
       
  1389 				Message("%s", start);
       
  1390 
       
  1391 			// step over newline
       
  1392 			while ((count < length - 1) && (*eol == '\r') || (*eol == '\n'))
       
  1393 			{
       
  1394 				count++;
       
  1395 				eol++;
       
  1396 			}
       
  1397 
       
  1398 			if (count < length - 1)
       
  1399 				start = eol;
       
  1400 		}
       
  1401 
       
  1402 		Message(DOTTED_LINE);
       
  1403 		LeaveCriticalSection(&CriticalSection);
       
  1404 	}
       
  1405 	else
       
  1406 		Message("No information returned from device");
       
  1407 }
       
  1408 
       
  1409 //----------------------------------------------------------------------------
       
  1410 // Store some data in a public defined char* pointer
       
  1411 //  (currently iTEFSharedData and pDeviceInfo)
       
  1412 void CSTATEngine::StoreData( char* aData, unsigned long aLength, char*& aOutputPtr )
       
  1413 {
       
  1414 
       
  1415 	receivedData.Empty();
       
  1416 	receivedData = aData;
       
  1417 
       
  1418 	if( aOutputPtr )
       
  1419 	{
       
  1420 		delete [] aOutputPtr;
       
  1421 		aOutputPtr = NULL;
       
  1422 	}
       
  1423 
       
  1424 	if( aData && aLength )
       
  1425 	{
       
  1426 		aOutputPtr = new char[aLength + 1];
       
  1427 		if( aOutputPtr )
       
  1428 		{
       
  1429 			// skip over leading CR/LF's
       
  1430 			char *p = aData;
       
  1431 			while (p && (*p) && (*p == '\r') || (*p == '\n'))
       
  1432 				p++;
       
  1433 			strcpy(aOutputPtr, p);
       
  1434 		}
       
  1435 	}
       
  1436 }
       
  1437 
       
  1438 //----------------------------------------------------------------------------
       
  1439 // Translate a connection type to a string
       
  1440 CString CSTATEngine::GetConnection(STATCONNECTTYPE eConnectType)
       
  1441 {
       
  1442 	CString connection;
       
  1443 
       
  1444 	switch(eConnectType)
       
  1445 	{
       
  1446 	case SymbianSocket:
       
  1447 		connection = _T("SymbianSocket");
       
  1448 		break;
       
  1449 	case SymbianSerial:
       
  1450 		connection = _T("SymbianSerial");
       
  1451 		break;
       
  1452 	case SymbianInfrared:
       
  1453 		connection = _T("SymbianInfrared");
       
  1454 		break;
       
  1455 	case SymbianBluetooth:
       
  1456 		connection = _T("SymbianBluetooth");
       
  1457 		break;
       
  1458 	case SymbianUsb:
       
  1459 		connection = _T("SymbianUsb");
       
  1460 		break;
       
  1461 	default:
       
  1462 		connection = _T("SymbianInvalid");
       
  1463 		break;
       
  1464 	};
       
  1465 
       
  1466 	return connection;
       
  1467 }
       
  1468 
       
  1469 
       
  1470 //----------------------------------------------------------------------------
       
  1471 //  Sets a data socket to read/write file streams
       
  1472 //
       
  1473 int CSTATEngine::SetSocket(const char *ip, const int port)
       
  1474 {
       
  1475 
       
  1476 	//initialise winsock
       
  1477 	WSAStartup( MAKEWORD(2,2), &wsaData );
       
  1478 	
       
  1479 	dataSocket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
       
  1480 
       
  1481     if ( dataSocket == INVALID_SOCKET ) 
       
  1482 	{
       
  1483         dataSocket=NULL;
       
  1484 		return E_SOCKETCREATE; 
       
  1485     }
       
  1486 
       
  1487 	// Connect to a server.
       
  1488     sockaddr_in clientService;
       
  1489 
       
  1490     clientService.sin_family = AF_INET;
       
  1491     clientService.sin_addr.s_addr = inet_addr( ip );
       
  1492     clientService.sin_port = htons( port );
       
  1493 
       
  1494     if ( connect( dataSocket, (SOCKADDR*) &clientService, sizeof(clientService) ) == SOCKET_ERROR) 
       
  1495 	{
       
  1496         ReleaseSocket();
       
  1497 		return E_SOCKETCONNECT;
       
  1498     }
       
  1499 	else
       
  1500 	{
       
  1501 		return ITS_OK;
       
  1502 	}
       
  1503 
       
  1504 
       
  1505 	
       
  1506 }
       
  1507 
       
  1508 int CSTATEngine::ReleaseSocket()
       
  1509 {
       
  1510 	int ret = ITS_OK;
       
  1511 
       
  1512 	//release the socket
       
  1513 	if( closesocket(dataSocket) == SOCKET_ERROR)
       
  1514 	{
       
  1515 		ret = E_SOCKETCLOSE;
       
  1516 	}
       
  1517 
       
  1518 
       
  1519 	//cleanup winsock
       
  1520 	WSACleanup();
       
  1521 
       
  1522 	dataSocket=NULL;
       
  1523 
       
  1524 	return ret;
       
  1525 	
       
  1526 }
       
  1527 
       
  1528 
       
  1529 //----------------------------------------------------------------------------
       
  1530 // Read from the board and write to the data socket
       
  1531 //
       
  1532 
       
  1533 void CSTATEngine::WriteToSocket(const char *data, int *length)
       
  1534 {
       
  1535 	// Send data.
       
  1536    	*length = send( dataSocket, data, *length , 0 );
       
  1537 }
       
  1538 
       
  1539 
       
  1540 
       
  1541 //----------------------------------------------------------------------------
       
  1542 // Read from the data socket and send to the board
       
  1543 //
       
  1544 void CSTATEngine::ReadFromSocket(char *data, int *length)
       
  1545 {
       
  1546 	int bufferSize = 0xFF;
       
  1547 
       
  1548 	if(*length >= bufferSize)
       
  1549 	{
       
  1550 	
       
  1551 		int packetLength = *length;
       
  1552 		
       
  1553 		int totalRead = 0;
       
  1554 		int iterRead = 0;
       
  1555 
       
  1556 		// Receive data to fill a packet
       
  1557 		while(totalRead <= packetLength - bufferSize)
       
  1558 		{
       
  1559 			iterRead = recv( dataSocket, data + totalRead, bufferSize, 0 );
       
  1560 			if(iterRead == 0)
       
  1561 				break;
       
  1562 			totalRead += iterRead;
       
  1563 		}
       
  1564 
       
  1565 		*length = totalRead;
       
  1566 	}
       
  1567 	else
       
  1568 	{
       
  1569 		*length = recv( dataSocket, data, *length, 0 );
       
  1570 	}
       
  1571 }
       
  1572 
       
  1573 
       
  1574 
       
  1575 
       
  1576 
       
  1577 
       
  1578 
       
  1579  
       
  1580