installationservices/swi/source/sishelper/uissclienthandler.cpp
changeset 0 ba25891c3a9e
child 25 98b66e4fb0be
child 34 741e5bba2bd1
equal deleted inserted replaced
-1:000000000000 0:ba25891c3a9e
       
     1 /*
       
     2 * Copyright (c) 2004-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 the License "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 * Implementation of Swi::CUissClientHandler class which is the client-side 
       
    16 * part of the reverse completion mechanism used by SWI to communicate with 
       
    17 * the UI
       
    18 *
       
    19 */
       
    20 
       
    21 
       
    22 /**
       
    23  @file
       
    24 */
       
    25 #include "uissclienthandler.h"
       
    26 #include "uisscommand.h"
       
    27 #include "uisssession.h"
       
    28 #include "../source/uiss/server/uissserver.h"
       
    29 #include "sishelper.h"
       
    30 #include "sisregistrypackage.h"
       
    31 #include "writestream.h"
       
    32 // UI Support Server Commands
       
    33 #include "commands/installdialog.h"
       
    34 #include "commands/grantcapabilitiesdialog.h"
       
    35 #include "commands/languagedialog.h"
       
    36 #include "commands/applicationsinusedialog.h"
       
    37 #include "commands/drivedialog.h"
       
    38 #include "commands/cannotoverwritefiledialog.h"
       
    39 #include "commands/dependencybreakdialog.h"
       
    40 #include "commands/deviceincompatibility.h"
       
    41 #include "commands/missingdependency.h"
       
    42 #include "commands/errordialog.h"
       
    43 #include "commands/handlecancellableinstallevent.h"
       
    44 #include "commands/handleinstallevent.h"
       
    45 #include "commands/ocspresultdialog.h"
       
    46 #include "commands/optionsdialog.h"
       
    47 #include "commands/questiondialog.h"
       
    48 #include "commands/upgradedialog.h"
       
    49 #include "commands/uninstalldialog.h"
       
    50 #include "commands/securitywarningdialog.h"
       
    51 #include "commands/textdialog.h"
       
    52 #include "log.h"
       
    53 
       
    54 #ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
       
    55 #include "cleanuputils.h"
       
    56 #include <usif/sif/sifcommon.h>
       
    57 const TInt KCompInfoBufferSize=4*1024;
       
    58 #endif
       
    59 
       
    60 namespace Swi
       
    61 {
       
    62 //
       
    63 // A cancel handler
       
    64 //
       
    65 class InternalCancelHandler : public MCancelHandler
       
    66 	{
       
    67 public:
       
    68 	InternalCancelHandler(CUissClientHandler& aUissClientHandler);
       
    69 	void HandleCancel();
       
    70 private:
       
    71 	CUissClientHandler& iUissClientHandler;
       
    72 	};
       
    73 
       
    74 InternalCancelHandler::InternalCancelHandler(
       
    75 	CUissClientHandler& aUissClientHandler)
       
    76 :	iUissClientHandler(aUissClientHandler)
       
    77 	{
       
    78 	}
       
    79 
       
    80 void InternalCancelHandler::HandleCancel()
       
    81 	{
       
    82 	iUissClientHandler.CancelOperation();
       
    83 	}
       
    84 
       
    85 CUissClientHandler* CUissClientHandler::NewLC(MUiHandler& aUiHandler, TBool aActiveObjectMode)
       
    86 	{
       
    87 	CUissClientHandler* self=new(ELeave) CUissClientHandler(aUiHandler, aActiveObjectMode);
       
    88 	CleanupStack::PushL(self);
       
    89 	self->ConstructL();
       
    90 	return self;
       
    91 	}
       
    92 
       
    93 CUissClientHandler* CUissClientHandler::NewL(MUiHandler& aUiHandler, TBool aActiveObjectMode)
       
    94 	{
       
    95 	CUissClientHandler* self=NewLC(aUiHandler, aActiveObjectMode);
       
    96 	CleanupStack::Pop(self);
       
    97 	return self;
       
    98 	}
       
    99 
       
   100 CUissClientHandler::CUissClientHandler(MUiHandler& aUiHandler, TBool aActiveObjectMode)
       
   101         : CActive(EPriorityStandard),
       
   102           iUiHandler(aUiHandler),
       
   103 		  iPtrIntoBuf(0,0),
       
   104           iActiveObjectMode(aActiveObjectMode),
       
   105 		  iPtrIntoArgsStream(0,0)
       
   106 		  #ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
       
   107 		  ,iCompInfoBufPtr(0,0)
       
   108 		  #endif
       
   109 	{
       
   110     if (iActiveObjectMode)
       
   111 		{
       
   112 		CActiveScheduler::Add(this);
       
   113 		}
       
   114 	}
       
   115 
       
   116 void CUissClientHandler::WaitForSisHelperShutdown()
       
   117 	{	
       
   118 	if(iSisHelper.Handle() > 0)
       
   119 		{
       
   120 		TRequestStatus reqStatus;
       
   121 		iSisHelper.Logon(reqStatus);
       
   122 		User::WaitForRequest(reqStatus);
       
   123 		iSisHelper.Close();
       
   124 		}		
       
   125 	}
       
   126 	
       
   127 CUissClientHandler::~CUissClientHandler()
       
   128 	{
       
   129 	//Cancel any outstanding request
       
   130 	CancelOperation();
       
   131 
       
   132 	WaitForSisHelperShutdown();
       
   133     if (iActiveObjectMode)
       
   134 		{
       
   135 		CActive::Cancel(); // Make sure we are cancelled before deletion
       
   136 		}
       
   137 
       
   138 	delete iCancelHandler;
       
   139     delete iArgsStream;
       
   140 	iUissSession.Close();
       
   141 	delete iBuf;
       
   142 	#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
       
   143     delete iCompInfoBuffer;
       
   144 	#endif
       
   145 	}
       
   146 
       
   147 /**
       
   148  * Allocates a buffer for reverse-completion commands. The buffer is going to 
       
   149  * be resized in case it is not sufficient for a dialog command.
       
   150  */
       
   151 void CUissClientHandler::ConstructL()
       
   152 	{
       
   153 	iCancelHandler=new(ELeave) InternalCancelHandler(*this);
       
   154 	AllocBufL(KBufSize);// Allocate the initial r/c buffer
       
   155 	User::LeaveIfError(StartUiss()); // Start UISS
       
   156 	User::LeaveIfError(iUissSession.Connect()); // Connect to UISS
       
   157 	}
       
   158 
       
   159 void CUissClientHandler::AllocBufL(TInt aSize)
       
   160 	{
       
   161     HBufC8* buf=HBufC8::NewL(aSize);
       
   162     delete iBuf;
       
   163     iBuf=buf;
       
   164     }
       
   165 
       
   166 void CUissClientHandler::HandleOverflowL()
       
   167 	{
       
   168 	// Reallocate the buffer to the size received in parameter 1
       
   169 	TInt size=0;
       
   170 	TPckg<TInt> theSize(size);
       
   171 	theSize.Copy(iBuf->Left(sizeof(TInt)));
       
   172 	AllocBufL(size);
       
   173 	}
       
   174 	
       
   175 #ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
       
   176 void CUissClientHandler::AllocCompInfoBufL(TInt aSize)
       
   177 	{
       
   178     HBufC8* buf = HBufC8::NewL(aSize);
       
   179     delete iCompInfoBuffer;
       
   180     iCompInfoBuffer = buf;
       
   181     }
       
   182 #endif
       
   183 
       
   184 ///\short Creates a command handler object for the specified dialog request
       
   185 CUissCmdHandler* CUissClientHandler::UissCmdHandlerFactoryL(TInt aCommand) const
       
   186 	{
       
   187 	switch (aCommand)
       
   188 		{
       
   189 		case CUissSession::KMessageApplicationsInUseDialog:
       
   190 			return new(ELeave) CApplicationsInUseDialogCmdHandler(iUiHandler);
       
   191 		case CUissSession::KMessageCannotOverwriteFileDialog:
       
   192 			return new(ELeave) CCannotOverwriteFileDialogCmdHandler(iUiHandler);
       
   193 		
       
   194 		case CUissSession::KMessageDependencyBreakDialog:
       
   195 			return new(ELeave) CDependencyBreakDialogCmdHandler(iUiHandler);
       
   196 		case CUissSession::KMessageDeviceIncompatibility:
       
   197 			return new(ELeave) CDeviceIncompatibilityDialogCmdHandler(iUiHandler);
       
   198 		case CUissSession::KMessageMissingDependency:
       
   199 			return new(ELeave) CMissingDependencyDialogCmdHandler(iUiHandler);
       
   200 		case CUissSession::KMessageDriveDialog:
       
   201 			return new(ELeave) CDriveDialogCmdHandler(iUiHandler);
       
   202 		case CUissSession::KMessageErrorDialog:
       
   203 			return new(ELeave) CErrorDialogCmdHandler(iUiHandler);
       
   204 		case CUissSession::KMessageGrantCapabilitiesDialog:
       
   205 			return new(ELeave) CGrantCapabilitiesDialogCmdHandler(iUiHandler);	
       
   206 		case CUissSession::KMessageHandleCancellableInstallEvent:
       
   207 			return new(ELeave) CHandleCancellableInstallEventCmdHandler(iUiHandler, 
       
   208 				*iCancelHandler);
       
   209 		case CUissSession::KMessageHandleInstallEvent:
       
   210 			return new(ELeave) CHandleInstallEventCmdHandler(iUiHandler);
       
   211 		case CUissSession::KMessageInstallDialog:
       
   212 			return new(ELeave) CInstallDialogCmdHandler(iUiHandler);
       
   213 		case CUissSession::KMessageLanguageDialog:
       
   214 			return new(ELeave) CLanguageDialogCmdHandler(iUiHandler);
       
   215 		case CUissSession::KMessageOcspResultDialog:
       
   216 			return new(ELeave) COcspResultDialogCmdHandler(iUiHandler);
       
   217 		case CUissSession::KMessageOptionsDialog:
       
   218 			return new(ELeave) COptionsDialogCmdHandler(iUiHandler);
       
   219 		case CUissSession::KMessageQuestionDialog:
       
   220 			return new(ELeave) CQuestionDialogCmdHandler(iUiHandler);
       
   221 		case CUissSession::KMessageSecurityWarningDialog:
       
   222 			return new(ELeave) CSecurityWarningDialogCmdHandler(iUiHandler);
       
   223 		case CUissSession::KMessageUninstallDialog:
       
   224 			return new(ELeave) CUninstallDialogCmdHandler(iUiHandler);
       
   225 		
       
   226 		case CUissSession::KMessageUpgradeDialog:
       
   227 			return new(ELeave) CUpgradeDialogCmdHandler(iUiHandler);
       
   228 		
       
   229 		case CUissSession::KMessageTextDialog:
       
   230 			return new(ELeave) CTextDialogCmdHandler(iUiHandler);
       
   231 					
       
   232 		default:
       
   233 			return NULL;
       
   234 		}
       
   235 	}
       
   236 
       
   237 void CUissClientHandler::InitializeArgStreamL(const CInstallPrefs& aInstallPrefs)
       
   238 	{
       
   239 	// Stream out install parameters. Cannot do this in UISSCLIENT because 
       
   240 	// the code is in LAUNCHER which depends on UISSCLIENT.
       
   241     delete iArgsStream;
       
   242     iArgsStream = 0;
       
   243 	iArgsStream = CWriteStream::NewL();
       
   244 	*iArgsStream << aInstallPrefs;
       
   245     // Save ptr for args (must persist whilst server is processing)
       
   246 	iPtrIntoArgsStream.Set(iArgsStream->Ptr());	
       
   247 	}
       
   248 	
       
   249 void CUissClientHandler::InstallL(const CInstallPrefs& aInstallPrefs, const RArray<TInt>& aDeviceSupportedLanguages, TRequestStatus& aRequestStatus, RThread& aServer)
       
   250 	{
       
   251     iState = KUissClientInstalling;
       
   252     iClientStatus = &aRequestStatus;
       
   253     
       
   254     // Save ptr for data returned by request (must persist whilst server is processing)
       
   255 	iPtrIntoBuf.Set(iBuf->Des());
       
   256 
       
   257 	InitializeArgStreamL(aInstallPrefs);
       
   258 	iArgsStream->Stream().WriteInt32L(aDeviceSupportedLanguages.Count());
       
   259 	//Streaming set of languages that device supports
       
   260 	TInt noOfDeviceSupportedLanguages = aDeviceSupportedLanguages.Count();
       
   261 	for(TInt i=0;i<noOfDeviceSupportedLanguages;i++)
       
   262 		{
       
   263 		iArgsStream->Stream().WriteInt32L(aDeviceSupportedLanguages[i]);
       
   264 		}
       
   265 	// Save ptr for args (must persist whilst server is processing)
       
   266 	iPtrIntoArgsStream.Set(iArgsStream->Ptr());	
       
   267 		
       
   268     // Issue initial request
       
   269     iUissSession.Install(iPtrIntoArgsStream, iPtrIntoBuf, iStatus);
       
   270     if (iActiveObjectMode)
       
   271 		{
       
   272 		SetActive();
       
   273 		}
       
   274 
       
   275     // Update client's TRequestStatus object
       
   276     *iClientStatus = KRequestPending;
       
   277     iSisHelper = aServer;
       
   278 	}
       
   279 
       
   280 #ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
       
   281 void CUissClientHandler::GetComponentInfoL(const CInstallPrefs& aInstallPrefs, Usif::CComponentInfo& aComponentInfo, TRequestStatus& aRequestStatus, RThread& aServer)
       
   282 	{	
       
   283     iState = KUissClientGettingCompInfo;
       
   284     iClientStatus = &aRequestStatus;
       
   285     	
       
   286     // Store the component info reference to the class reference. So that, the same will be 
       
   287     // populated after getting the asynchronous method completed.
       
   288     iComponentInfo = &aComponentInfo;
       
   289     
       
   290 	InitializeArgStreamL(aInstallPrefs);
       
   291 	
       
   292 	AllocCompInfoBufL(KCompInfoBufferSize);	
       
   293 	
       
   294 	// Save the pointer for component info collection buffer
       
   295 	iCompInfoBufPtr.Set(iCompInfoBuffer->Des());
       
   296 
       
   297     // Issue get component info request
       
   298     iUissSession.GetComponentInfo(iPtrIntoArgsStream, iCompInfoBufPtr, iStatus);
       
   299 
       
   300 	// There is no synchronous API for GetComponentInfo
       
   301 	__ASSERT_ALWAYS(iActiveObjectMode, User::Invariant());
       
   302 	SetActive();
       
   303 
       
   304     // Update client's TRequestStatus object
       
   305     *iClientStatus = KRequestPending;
       
   306     iSisHelper = aServer;	
       
   307 	}
       
   308 #endif
       
   309 
       
   310 void CUissClientHandler::UninstallL(const CSisRegistryPackage& aPackage, TRequestStatus& aRequestStatus)
       
   311 	{
       
   312     iState = KUissClientUninstalling;
       
   313     iClientStatus = &aRequestStatus;
       
   314 
       
   315     // Save ptr for data returned by request (must persist whilst server is processing)
       
   316     iPtrIntoBuf.Set(iBuf->Des());
       
   317 
       
   318     delete iArgsStream;
       
   319     iArgsStream = 0;
       
   320 	iArgsStream = CWriteStream::NewL();
       
   321     *iArgsStream << aPackage;
       
   322     // Save ptr for args (must persist whilst server is processing)
       
   323 	iPtrIntoArgsStream.Set(iArgsStream->Ptr());
       
   324 
       
   325 	// Issue initial request
       
   326     iUissSession.Uninstall(iPtrIntoArgsStream, iPtrIntoBuf, iStatus);
       
   327     if (iActiveObjectMode)
       
   328 		{
       
   329 		SetActive();
       
   330 		}
       
   331 
       
   332     // Update client's TRequestStatus object
       
   333     *iClientStatus = KRequestPending;
       
   334 	}
       
   335 
       
   336 void CUissClientHandler::CancelOperation()
       
   337 	{
       
   338 	if (iState == KUissClientIdle)
       
   339 		{
       
   340 		return;
       
   341 		}
       
   342 	
       
   343 	// User called this so must have an outstanding request with us.
       
   344 
       
   345 	// First tell the Uiss that we want to cancel the current
       
   346 	// operation.
       
   347 	//
       
   348 	// If we have an outstanding Uiss request, this will complete (with
       
   349 	// KErrCancel) when the operation has terminated.
       
   350 	//
       
   351 	// If we are called inside a dialog callback, then there is no
       
   352 	// outstanding Uiss request at the moment. When the dialog
       
   353 	// returns, we will issue a request, which will complete (with
       
   354 	// KErrCancel) when the operation has terminated.
       
   355 	(void)iUissSession.Cancel();
       
   356 	}
       
   357 
       
   358 void CUissClientHandler::WorkUntilCompleteL()
       
   359 	{
       
   360 	// Keep processing UISS responses and issuing new requests
       
   361 	// until we update the client status to non-pending.
       
   362 	while(iClientStatus && *iClientStatus == KRequestPending) 
       
   363 		{
       
   364 		User::WaitForRequest(iStatus);
       
   365 		TRAPD(err,RunL());
       
   366 		if(err != KErrNone)
       
   367 			{	
       
   368 			RunError(err);
       
   369 			}
       
   370 		}
       
   371 	}
       
   372 
       
   373 TBool CUissClientHandler::IsBusy()
       
   374 	{
       
   375 	return iState != KUissClientIdle;
       
   376 	}
       
   377 
       
   378 
       
   379 //
       
   380 // Code necessary to run UISS in the same process but in a different thread
       
   381 //
       
   382 TInt CUissClientHandler::StartUiss()
       
   383 	{
       
   384 	const TInt KUissServerStackSize=0x2000;
       
   385 	const TInt KUissServerInitHeapSize=0x1000;
       
   386 	const TInt KUissServerMaxHeapSize=0x1000000;
       
   387 	
       
   388 	
       
   389 	TThreadFunction entryPoint=UissThreadFunction;
       
   390 	//TUiSupportStartParams uiSupportParams(aUiHandler);
       
   391 	// The owner of the new thread will be the process, otherwise if the 
       
   392 	// current thread dies, the server thread will die, too.
       
   393 	RThread server;
       
   394 	TInt err = KErrNone;
       
   395 		
       
   396 	for (TInt retry=0; retry < 2; ++retry)
       
   397 		{
       
   398 		err = server.Create(KUissServerName, entryPoint, 
       
   399 		KUissServerStackSize, KUissServerInitHeapSize, KUissServerMaxHeapSize,
       
   400 		NULL, EOwnerThread);
       
   401 		
       
   402 		if (err == KErrAlreadyExists)
       
   403 			{
       
   404 			User::After(30000);	
       
   405 			}
       
   406 		else
       
   407 			{
       
   408 			break;
       
   409 			}
       
   410 		}
       
   411 		
       
   412 	if (err==KErrAlreadyExists)
       
   413 		{
       
   414 		return KErrServerBusy;
       
   415 		}
       
   416 	if (err != KErrNone)
       
   417 		{
       
   418 		return err;
       
   419 		}
       
   420 	
       
   421 	// Synchronise with the process to make sure it hasn't died straight away
       
   422 	TRequestStatus stat;
       
   423 	server.Rendezvous(stat);
       
   424 	if (stat != KRequestPending)
       
   425 		{
       
   426 		// logon failed - server is not yet running, so cannot have terminated
       
   427 		server.Kill(0); // Abort startup
       
   428 		}
       
   429 	else
       
   430 		{
       
   431 		// logon OK - start the server
       
   432 		server.Resume();
       
   433 		}
       
   434 	// Wait to synchronise with server - if it dies in the meantime, it
       
   435 	// also gets completed
       
   436 	User::WaitForRequest(stat);	
       
   437 	// We can't use the 'exit reason' if the server panicked as this
       
   438 	// is the panic 'reason' and may be '0' which cannot be distinguished
       
   439 	// from KErrNone
       
   440 	TInt r=(server.ExitType()==EExitPanic) ? KErrGeneral : stat.Int();
       
   441 	server.Close();
       
   442 	return r;
       
   443 	}
       
   444 
       
   445 // Entry point for the thread the UISS runs in
       
   446 TInt CUissClientHandler::UissThreadFunction(TAny *)
       
   447 	{
       
   448 	__UHEAP_MARK;
       
   449 	CTrapCleanup* cleanup = CTrapCleanup::New(); // get clean-up stack
       
   450 	
       
   451 	CActiveScheduler* scheduler=new(ELeave) CActiveScheduler;
       
   452 	CActiveScheduler::Install(scheduler);
       
   453 	CUissServer* server=NULL;
       
   454 	
       
   455 	TRAPD(err, server=CUissServer::NewL());
       
   456 	if (err==KErrNone)
       
   457 		{
       
   458 		RThread::Rendezvous(KErrNone);
       
   459 		scheduler->Start();
       
   460 		}
       
   461 	
       
   462 	delete server;
       
   463 	
       
   464 	CActiveScheduler::Install(NULL);
       
   465 	delete scheduler;
       
   466 	delete cleanup; // destroy clean-up stack
       
   467 	__UHEAP_MARKEND;
       
   468 	return KErrNone;
       
   469 	}
       
   470 
       
   471 void CUissClientHandler::RunL()
       
   472     {
       
   473     TInt err = iStatus.Int();
       
   474 	iPtrIntoBuf.Set(iBuf->Des()); // Get ptr to our return buffer
       
   475 
       
   476 	DEBUG_PRINTF2(_L8("Sis Helper - UISS Client Handler, RunL(). Status: %d."), err);
       
   477 
       
   478 	
       
   479     if (err==KErrOverflow 
       
   480 #ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK	
       
   481 		&& iState != KUissClientGettingCompInfo // We don't support overflow management for component info
       
   482 #endif
       
   483 		)
       
   484         {
       
   485         // Grow the respective buffer buffer and re-issue "request".
       
   486         // There should now be space for the UISS server to copy in its dialogue message.
       
   487         HandleOverflowL();
       
   488         iPtrIntoBuf.Set(iBuf->Des());
       
   489 		iUissSession.BufferReallocated(iPtrIntoBuf, iStatus);
       
   490 
       
   491 		if (iActiveObjectMode)
       
   492 			{
       
   493 			SetActive();
       
   494 			}
       
   495 		return;
       
   496 		}
       
   497 	else
       
   498 		{
       
   499 		if (err>CUissSession::KMsgSeparatorMinimumSwisMessage && 
       
   500 			err<CUissSession::KMsgSeparatorMaximumSwisMessage)
       
   501 			{
       
   502 			// this is a dialog request, unmarshal parameters and display 
       
   503 			// the dialog
       
   504 			CUissCmdHandler* cmdHandler=UissCmdHandlerFactoryL(err);
       
   505 			if (!cmdHandler)
       
   506 				{
       
   507 				User::Leave(KErrNotSupported);
       
   508 				}
       
   509 			
       
   510 			CleanupStack::PushL(cmdHandler);
       
   511 			// Note that the callback might call CancelOperation which
       
   512 			// would update iState...
       
   513 			cmdHandler->HandleMessageL(iPtrIntoBuf, iPtrIntoBuf);
       
   514 			CleanupStack::PopAndDestroy(cmdHandler);
       
   515 			}
       
   516 		else
       
   517 			{
       
   518 			#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
       
   519 			// Request has been completed successfully. So, now construct the 
       
   520 			// component info from the buffer which is populated from the SWI server.
       
   521 			if (err == KErrNone  && iState == KUissClientGettingCompInfo)
       
   522 				{
       
   523 				ConstructCompInfoFromBufferL();
       
   524 				}			
       
   525 			#endif
       
   526 			// Either KErrNone or some sort of error status - in any case the processing has finished
       
   527 			iState = KUissClientIdle;			
       
   528 			}
       
   529 		}
       
   530 	
       
   531 	// Re-issue request, if we are still installing/uninstalling
       
   532 	switch(iState)
       
   533 		{
       
   534 	case KUissClientInstalling:
       
   535 	case KUissClientUninstalling:
       
   536 		iUissSession.CompleteDialog(KErrNone, iPtrIntoBuf, iStatus);
       
   537 		if (iActiveObjectMode)
       
   538 			{
       
   539 			SetActive();
       
   540 			}
       
   541 		return;
       
   542 			
       
   543 	case KUissClientIdle:
       
   544 		// All done, or failed...
       
   545 		delete iArgsStream;
       
   546 		iArgsStream = 0;
       
   547 		//Wait for the death of SisHelper
       
   548 		WaitForSisHelperShutdown();	
       
   549 		// Complete user request (also sets iClientStatus to 0)
       
   550 		ASSERT(iClientStatus);
       
   551 		User::RequestComplete(iClientStatus, err);
       
   552 		return;
       
   553 		}
       
   554 	ASSERT(false);
       
   555     }
       
   556 
       
   557 
       
   558 TInt CUissClientHandler::RunError(TInt aError)
       
   559 	{
       
   560 	DEBUG_PRINTF2(_L8("Sis Helper - UISS Client Handler, RunError. Error: %d."), aError);
       
   561 	// Pass failure code on to our client.
       
   562 	iPtrIntoBuf.Zero();
       
   563 	iUissSession.CompleteDialog(aError, iPtrIntoBuf, iStatus);
       
   564     if (iActiveObjectMode)
       
   565 		{
       
   566 		SetActive();
       
   567 		}
       
   568 	return KErrNone; // Do not crash the CActiveScheduler.
       
   569 	}
       
   570 
       
   571 void CUissClientHandler::DoCancel()
       
   572     {
       
   573     DEBUG_PRINTF(_L8("Sis Helper - UISS Client Handler, Cancelling."));
       
   574     
       
   575 	// Normally NEVER called because the application should have
       
   576 	// waited for the original request to complete!
       
   577 	
       
   578 	// We can NOT simply call CancelOperation, because when we return
       
   579 	// into the framework Cancel function it will block on our
       
   580 	// iStatus, which would stop the active scheduler and hence stop
       
   581 	// the CancelOperation from being actioned.
       
   582 
       
   583 	// Do an emergency abort.....
       
   584 
       
   585 	// First kill our helper threads
       
   586 	
       
   587 	// SIS helper thread/server
       
   588 	CSisHelperServer::Abort();
       
   589 	
       
   590 	// UI helper thread/server
       
   591 	TFullName fullName = RProcess().FullName();
       
   592 	fullName.Append(':');
       
   593 	fullName.Append(':');
       
   594 	fullName.Append(KUissServerName);
       
   595 
       
   596 	RThread server;
       
   597 	TInt err = server.Open(fullName);
       
   598 	if (err == KErrNone)
       
   599 		{
       
   600 		server.Terminate(KErrAbort);
       
   601 		server.Close();
       
   602 		}
       
   603 	
       
   604 	// Now complete any client request
       
   605 	if (iClientStatus)
       
   606 		{
       
   607 		User::RequestComplete(iClientStatus, err);
       
   608 		}
       
   609     }
       
   610     
       
   611 #ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
       
   612 void CUissClientHandler::ConstructCompInfoFromBufferL()
       
   613     {    
       
   614     // create a stream based on the buffer
       
   615 	RDesReadStream stream(*iCompInfoBuffer);
       
   616 	CleanupClosePushL(stream);
       
   617 	
       
   618 	CNativeComponentInfo* nativeCompInfo = CNativeComponentInfo::NewLC();
       
   619 	nativeCompInfo->InternalizeL(stream);
       
   620 		
       
   621 	// UISS and SWI cannot use Usif::CComponentInfo directly, as it is implemented in a non-TCB DLL. For this reason, a private structure maintained (CNativeComponentInfo),
       
   622 	// which is returned by SWI and is converted here to the CComponentInfo according to the USIF interface
       
   623 	Usif::CComponentInfo::CNode* rootNode = MapToComponentInfoL(*nativeCompInfo);
       
   624 	iComponentInfo->SetRootNodeL(rootNode);
       
   625 
       
   626 	CleanupStack::PopAndDestroy(nativeCompInfo);
       
   627 	CleanupStack::PopAndDestroy(&stream);
       
   628     }
       
   629 
       
   630 Usif::CComponentInfo::CNode* CUissClientHandler::MapToComponentInfoL(CNativeComponentInfo& aNativeComponentInfo)
       
   631 	{
       
   632 	// Create the array to store the children nodes.
       
   633 	RPointerArray<Usif::CComponentInfo::CNode> children;
       
   634 	CleanupResetAndDestroyPushL(children);
       
   635 	
       
   636 	// If there is any child for the current node, call this method with that child object.
       
   637 	// Continue this (recursively) until we get the leaf node in the embedded tree (with no children)
       
   638 	// and add the resultant node as one of the children and pass it to create the parent node further.
       
   639 	TInt count = aNativeComponentInfo.iChildren.Count();
       
   640 	for (TInt i = 0; i < count; ++i)
       
   641 		{
       
   642 		Usif::CComponentInfo::CNode* node = MapToComponentInfoL(*aNativeComponentInfo.iChildren[i]);
       
   643 		CleanupStack::PushL(node);
       
   644 		children.AppendL(node);
       
   645 		CleanupStack::Pop(node);
       
   646 		}
       
   647 		
       
   648 	// Create the CNode object using the appropriate parameters.
       
   649 	// children for leaf nodes (bottom most nodes in the embedded tree) will be null.
       
   650 	Usif::CComponentInfo::CNode* node = Usif::CComponentInfo::CNode::NewLC(
       
   651 										Usif::KSoftwareTypeNative(),
       
   652 										*(aNativeComponentInfo.iComponentName), 
       
   653 										*(aNativeComponentInfo.iVersion),
       
   654 										*(aNativeComponentInfo.iVendor),
       
   655 										static_cast<Usif::TScomoState>(aNativeComponentInfo.iScomoState),
       
   656 										static_cast<Usif::TInstallStatus>(aNativeComponentInfo.iInstallStatus),
       
   657 										aNativeComponentInfo.iComponentId,
       
   658 										*(aNativeComponentInfo.iGlobalComponentId),
       
   659 										static_cast<Usif::TAuthenticity>(aNativeComponentInfo.iAuthenticity),
       
   660 										aNativeComponentInfo.iUserGrantableCaps,
       
   661 										aNativeComponentInfo.iMaxInstalledSize,
       
   662 										aNativeComponentInfo.iHasExe,
       
   663 										&children);
       
   664 	CleanupStack::Pop(node);
       
   665 	CleanupStack::Pop(&children);
       
   666 	children.Close();
       
   667 	return (node);
       
   668 	}
       
   669 #endif
       
   670 } // namespace Swi