installationservices/swi/source/sishelper/uissclienthandler.cpp
changeset 0 ba25891c3a9e
child 17 741e5bba2bd1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/installationservices/swi/source/sishelper/uissclienthandler.cpp	Thu Dec 17 08:51:10 2009 +0200
@@ -0,0 +1,670 @@
+/*
+* Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+* Implementation of Swi::CUissClientHandler class which is the client-side 
+* part of the reverse completion mechanism used by SWI to communicate with 
+* the UI
+*
+*/
+
+
+/**
+ @file
+*/
+#include "uissclienthandler.h"
+#include "uisscommand.h"
+#include "uisssession.h"
+#include "../source/uiss/server/uissserver.h"
+#include "sishelper.h"
+#include "sisregistrypackage.h"
+#include "writestream.h"
+// UI Support Server Commands
+#include "commands/installdialog.h"
+#include "commands/grantcapabilitiesdialog.h"
+#include "commands/languagedialog.h"
+#include "commands/applicationsinusedialog.h"
+#include "commands/drivedialog.h"
+#include "commands/cannotoverwritefiledialog.h"
+#include "commands/dependencybreakdialog.h"
+#include "commands/deviceincompatibility.h"
+#include "commands/missingdependency.h"
+#include "commands/errordialog.h"
+#include "commands/handlecancellableinstallevent.h"
+#include "commands/handleinstallevent.h"
+#include "commands/ocspresultdialog.h"
+#include "commands/optionsdialog.h"
+#include "commands/questiondialog.h"
+#include "commands/upgradedialog.h"
+#include "commands/uninstalldialog.h"
+#include "commands/securitywarningdialog.h"
+#include "commands/textdialog.h"
+#include "log.h"
+
+#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+#include "cleanuputils.h"
+#include <usif/sif/sifcommon.h>
+const TInt KCompInfoBufferSize=4*1024;
+#endif
+
+namespace Swi
+{
+//
+// A cancel handler
+//
+class InternalCancelHandler : public MCancelHandler
+	{
+public:
+	InternalCancelHandler(CUissClientHandler& aUissClientHandler);
+	void HandleCancel();
+private:
+	CUissClientHandler& iUissClientHandler;
+	};
+
+InternalCancelHandler::InternalCancelHandler(
+	CUissClientHandler& aUissClientHandler)
+:	iUissClientHandler(aUissClientHandler)
+	{
+	}
+
+void InternalCancelHandler::HandleCancel()
+	{
+	iUissClientHandler.CancelOperation();
+	}
+
+CUissClientHandler* CUissClientHandler::NewLC(MUiHandler& aUiHandler, TBool aActiveObjectMode)
+	{
+	CUissClientHandler* self=new(ELeave) CUissClientHandler(aUiHandler, aActiveObjectMode);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	return self;
+	}
+
+CUissClientHandler* CUissClientHandler::NewL(MUiHandler& aUiHandler, TBool aActiveObjectMode)
+	{
+	CUissClientHandler* self=NewLC(aUiHandler, aActiveObjectMode);
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+CUissClientHandler::CUissClientHandler(MUiHandler& aUiHandler, TBool aActiveObjectMode)
+        : CActive(EPriorityStandard),
+          iUiHandler(aUiHandler),
+		  iPtrIntoBuf(0,0),
+          iActiveObjectMode(aActiveObjectMode),
+		  iPtrIntoArgsStream(0,0)
+		  #ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+		  ,iCompInfoBufPtr(0,0)
+		  #endif
+	{
+    if (iActiveObjectMode)
+		{
+		CActiveScheduler::Add(this);
+		}
+	}
+
+void CUissClientHandler::WaitForSisHelperShutdown()
+	{	
+	if(iSisHelper.Handle() > 0)
+		{
+		TRequestStatus reqStatus;
+		iSisHelper.Logon(reqStatus);
+		User::WaitForRequest(reqStatus);
+		iSisHelper.Close();
+		}		
+	}
+	
+CUissClientHandler::~CUissClientHandler()
+	{
+	//Cancel any outstanding request
+	CancelOperation();
+
+	WaitForSisHelperShutdown();
+    if (iActiveObjectMode)
+		{
+		CActive::Cancel(); // Make sure we are cancelled before deletion
+		}
+
+	delete iCancelHandler;
+    delete iArgsStream;
+	iUissSession.Close();
+	delete iBuf;
+	#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+    delete iCompInfoBuffer;
+	#endif
+	}
+
+/**
+ * Allocates a buffer for reverse-completion commands. The buffer is going to 
+ * be resized in case it is not sufficient for a dialog command.
+ */
+void CUissClientHandler::ConstructL()
+	{
+	iCancelHandler=new(ELeave) InternalCancelHandler(*this);
+	AllocBufL(KBufSize);// Allocate the initial r/c buffer
+	User::LeaveIfError(StartUiss()); // Start UISS
+	User::LeaveIfError(iUissSession.Connect()); // Connect to UISS
+	}
+
+void CUissClientHandler::AllocBufL(TInt aSize)
+	{
+    HBufC8* buf=HBufC8::NewL(aSize);
+    delete iBuf;
+    iBuf=buf;
+    }
+
+void CUissClientHandler::HandleOverflowL()
+	{
+	// Reallocate the buffer to the size received in parameter 1
+	TInt size=0;
+	TPckg<TInt> theSize(size);
+	theSize.Copy(iBuf->Left(sizeof(TInt)));
+	AllocBufL(size);
+	}
+	
+#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+void CUissClientHandler::AllocCompInfoBufL(TInt aSize)
+	{
+    HBufC8* buf = HBufC8::NewL(aSize);
+    delete iCompInfoBuffer;
+    iCompInfoBuffer = buf;
+    }
+#endif
+
+///\short Creates a command handler object for the specified dialog request
+CUissCmdHandler* CUissClientHandler::UissCmdHandlerFactoryL(TInt aCommand) const
+	{
+	switch (aCommand)
+		{
+		case CUissSession::KMessageApplicationsInUseDialog:
+			return new(ELeave) CApplicationsInUseDialogCmdHandler(iUiHandler);
+		case CUissSession::KMessageCannotOverwriteFileDialog:
+			return new(ELeave) CCannotOverwriteFileDialogCmdHandler(iUiHandler);
+		
+		case CUissSession::KMessageDependencyBreakDialog:
+			return new(ELeave) CDependencyBreakDialogCmdHandler(iUiHandler);
+		case CUissSession::KMessageDeviceIncompatibility:
+			return new(ELeave) CDeviceIncompatibilityDialogCmdHandler(iUiHandler);
+		case CUissSession::KMessageMissingDependency:
+			return new(ELeave) CMissingDependencyDialogCmdHandler(iUiHandler);
+		case CUissSession::KMessageDriveDialog:
+			return new(ELeave) CDriveDialogCmdHandler(iUiHandler);
+		case CUissSession::KMessageErrorDialog:
+			return new(ELeave) CErrorDialogCmdHandler(iUiHandler);
+		case CUissSession::KMessageGrantCapabilitiesDialog:
+			return new(ELeave) CGrantCapabilitiesDialogCmdHandler(iUiHandler);	
+		case CUissSession::KMessageHandleCancellableInstallEvent:
+			return new(ELeave) CHandleCancellableInstallEventCmdHandler(iUiHandler, 
+				*iCancelHandler);
+		case CUissSession::KMessageHandleInstallEvent:
+			return new(ELeave) CHandleInstallEventCmdHandler(iUiHandler);
+		case CUissSession::KMessageInstallDialog:
+			return new(ELeave) CInstallDialogCmdHandler(iUiHandler);
+		case CUissSession::KMessageLanguageDialog:
+			return new(ELeave) CLanguageDialogCmdHandler(iUiHandler);
+		case CUissSession::KMessageOcspResultDialog:
+			return new(ELeave) COcspResultDialogCmdHandler(iUiHandler);
+		case CUissSession::KMessageOptionsDialog:
+			return new(ELeave) COptionsDialogCmdHandler(iUiHandler);
+		case CUissSession::KMessageQuestionDialog:
+			return new(ELeave) CQuestionDialogCmdHandler(iUiHandler);
+		case CUissSession::KMessageSecurityWarningDialog:
+			return new(ELeave) CSecurityWarningDialogCmdHandler(iUiHandler);
+		case CUissSession::KMessageUninstallDialog:
+			return new(ELeave) CUninstallDialogCmdHandler(iUiHandler);
+		
+		case CUissSession::KMessageUpgradeDialog:
+			return new(ELeave) CUpgradeDialogCmdHandler(iUiHandler);
+		
+		case CUissSession::KMessageTextDialog:
+			return new(ELeave) CTextDialogCmdHandler(iUiHandler);
+					
+		default:
+			return NULL;
+		}
+	}
+
+void CUissClientHandler::InitializeArgStreamL(const CInstallPrefs& aInstallPrefs)
+	{
+	// Stream out install parameters. Cannot do this in UISSCLIENT because 
+	// the code is in LAUNCHER which depends on UISSCLIENT.
+    delete iArgsStream;
+    iArgsStream = 0;
+	iArgsStream = CWriteStream::NewL();
+	*iArgsStream << aInstallPrefs;
+    // Save ptr for args (must persist whilst server is processing)
+	iPtrIntoArgsStream.Set(iArgsStream->Ptr());	
+	}
+	
+void CUissClientHandler::InstallL(const CInstallPrefs& aInstallPrefs, const RArray<TInt>& aDeviceSupportedLanguages, TRequestStatus& aRequestStatus, RThread& aServer)
+	{
+    iState = KUissClientInstalling;
+    iClientStatus = &aRequestStatus;
+    
+    // Save ptr for data returned by request (must persist whilst server is processing)
+	iPtrIntoBuf.Set(iBuf->Des());
+
+	InitializeArgStreamL(aInstallPrefs);
+	iArgsStream->Stream().WriteInt32L(aDeviceSupportedLanguages.Count());
+	//Streaming set of languages that device supports
+	TInt noOfDeviceSupportedLanguages = aDeviceSupportedLanguages.Count();
+	for(TInt i=0;i<noOfDeviceSupportedLanguages;i++)
+		{
+		iArgsStream->Stream().WriteInt32L(aDeviceSupportedLanguages[i]);
+		}
+	// Save ptr for args (must persist whilst server is processing)
+	iPtrIntoArgsStream.Set(iArgsStream->Ptr());	
+		
+    // Issue initial request
+    iUissSession.Install(iPtrIntoArgsStream, iPtrIntoBuf, iStatus);
+    if (iActiveObjectMode)
+		{
+		SetActive();
+		}
+
+    // Update client's TRequestStatus object
+    *iClientStatus = KRequestPending;
+    iSisHelper = aServer;
+	}
+
+#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+void CUissClientHandler::GetComponentInfoL(const CInstallPrefs& aInstallPrefs, Usif::CComponentInfo& aComponentInfo, TRequestStatus& aRequestStatus, RThread& aServer)
+	{	
+    iState = KUissClientGettingCompInfo;
+    iClientStatus = &aRequestStatus;
+    	
+    // Store the component info reference to the class reference. So that, the same will be 
+    // populated after getting the asynchronous method completed.
+    iComponentInfo = &aComponentInfo;
+    
+	InitializeArgStreamL(aInstallPrefs);
+	
+	AllocCompInfoBufL(KCompInfoBufferSize);	
+	
+	// Save the pointer for component info collection buffer
+	iCompInfoBufPtr.Set(iCompInfoBuffer->Des());
+
+    // Issue get component info request
+    iUissSession.GetComponentInfo(iPtrIntoArgsStream, iCompInfoBufPtr, iStatus);
+
+	// There is no synchronous API for GetComponentInfo
+	__ASSERT_ALWAYS(iActiveObjectMode, User::Invariant());
+	SetActive();
+
+    // Update client's TRequestStatus object
+    *iClientStatus = KRequestPending;
+    iSisHelper = aServer;	
+	}
+#endif
+
+void CUissClientHandler::UninstallL(const CSisRegistryPackage& aPackage, TRequestStatus& aRequestStatus)
+	{
+    iState = KUissClientUninstalling;
+    iClientStatus = &aRequestStatus;
+
+    // Save ptr for data returned by request (must persist whilst server is processing)
+    iPtrIntoBuf.Set(iBuf->Des());
+
+    delete iArgsStream;
+    iArgsStream = 0;
+	iArgsStream = CWriteStream::NewL();
+    *iArgsStream << aPackage;
+    // Save ptr for args (must persist whilst server is processing)
+	iPtrIntoArgsStream.Set(iArgsStream->Ptr());
+
+	// Issue initial request
+    iUissSession.Uninstall(iPtrIntoArgsStream, iPtrIntoBuf, iStatus);
+    if (iActiveObjectMode)
+		{
+		SetActive();
+		}
+
+    // Update client's TRequestStatus object
+    *iClientStatus = KRequestPending;
+	}
+
+void CUissClientHandler::CancelOperation()
+	{
+	if (iState == KUissClientIdle)
+		{
+		return;
+		}
+	
+	// User called this so must have an outstanding request with us.
+
+	// First tell the Uiss that we want to cancel the current
+	// operation.
+	//
+	// If we have an outstanding Uiss request, this will complete (with
+	// KErrCancel) when the operation has terminated.
+	//
+	// If we are called inside a dialog callback, then there is no
+	// outstanding Uiss request at the moment. When the dialog
+	// returns, we will issue a request, which will complete (with
+	// KErrCancel) when the operation has terminated.
+	(void)iUissSession.Cancel();
+	}
+
+void CUissClientHandler::WorkUntilCompleteL()
+	{
+	// Keep processing UISS responses and issuing new requests
+	// until we update the client status to non-pending.
+	while(iClientStatus && *iClientStatus == KRequestPending) 
+		{
+		User::WaitForRequest(iStatus);
+		TRAPD(err,RunL());
+		if(err != KErrNone)
+			{	
+			RunError(err);
+			}
+		}
+	}
+
+TBool CUissClientHandler::IsBusy()
+	{
+	return iState != KUissClientIdle;
+	}
+
+
+//
+// Code necessary to run UISS in the same process but in a different thread
+//
+TInt CUissClientHandler::StartUiss()
+	{
+	const TInt KUissServerStackSize=0x2000;
+	const TInt KUissServerInitHeapSize=0x1000;
+	const TInt KUissServerMaxHeapSize=0x1000000;
+	
+	
+	TThreadFunction entryPoint=UissThreadFunction;
+	//TUiSupportStartParams uiSupportParams(aUiHandler);
+	// The owner of the new thread will be the process, otherwise if the 
+	// current thread dies, the server thread will die, too.
+	RThread server;
+	TInt err = KErrNone;
+		
+	for (TInt retry=0; retry < 2; ++retry)
+		{
+		err = server.Create(KUissServerName, entryPoint, 
+		KUissServerStackSize, KUissServerInitHeapSize, KUissServerMaxHeapSize,
+		NULL, EOwnerThread);
+		
+		if (err == KErrAlreadyExists)
+			{
+			User::After(30000);	
+			}
+		else
+			{
+			break;
+			}
+		}
+		
+	if (err==KErrAlreadyExists)
+		{
+		return KErrServerBusy;
+		}
+	if (err != KErrNone)
+		{
+		return err;
+		}
+	
+	// Synchronise with the process to make sure it hasn't died straight away
+	TRequestStatus stat;
+	server.Rendezvous(stat);
+	if (stat != KRequestPending)
+		{
+		// logon failed - server is not yet running, so cannot have terminated
+		server.Kill(0); // Abort startup
+		}
+	else
+		{
+		// logon OK - start the server
+		server.Resume();
+		}
+	// Wait to synchronise with server - if it dies in the meantime, it
+	// also gets completed
+	User::WaitForRequest(stat);	
+	// We can't use the 'exit reason' if the server panicked as this
+	// is the panic 'reason' and may be '0' which cannot be distinguished
+	// from KErrNone
+	TInt r=(server.ExitType()==EExitPanic) ? KErrGeneral : stat.Int();
+	server.Close();
+	return r;
+	}
+
+// Entry point for the thread the UISS runs in
+TInt CUissClientHandler::UissThreadFunction(TAny *)
+	{
+	__UHEAP_MARK;
+	CTrapCleanup* cleanup = CTrapCleanup::New(); // get clean-up stack
+	
+	CActiveScheduler* scheduler=new(ELeave) CActiveScheduler;
+	CActiveScheduler::Install(scheduler);
+	CUissServer* server=NULL;
+	
+	TRAPD(err, server=CUissServer::NewL());
+	if (err==KErrNone)
+		{
+		RThread::Rendezvous(KErrNone);
+		scheduler->Start();
+		}
+	
+	delete server;
+	
+	CActiveScheduler::Install(NULL);
+	delete scheduler;
+	delete cleanup; // destroy clean-up stack
+	__UHEAP_MARKEND;
+	return KErrNone;
+	}
+
+void CUissClientHandler::RunL()
+    {
+    TInt err = iStatus.Int();
+	iPtrIntoBuf.Set(iBuf->Des()); // Get ptr to our return buffer
+
+	DEBUG_PRINTF2(_L8("Sis Helper - UISS Client Handler, RunL(). Status: %d."), err);
+
+	
+    if (err==KErrOverflow 
+#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK	
+		&& iState != KUissClientGettingCompInfo // We don't support overflow management for component info
+#endif
+		)
+        {
+        // Grow the respective buffer buffer and re-issue "request".
+        // There should now be space for the UISS server to copy in its dialogue message.
+        HandleOverflowL();
+        iPtrIntoBuf.Set(iBuf->Des());
+		iUissSession.BufferReallocated(iPtrIntoBuf, iStatus);
+
+		if (iActiveObjectMode)
+			{
+			SetActive();
+			}
+		return;
+		}
+	else
+		{
+		if (err>CUissSession::KMsgSeparatorMinimumSwisMessage && 
+			err<CUissSession::KMsgSeparatorMaximumSwisMessage)
+			{
+			// this is a dialog request, unmarshal parameters and display 
+			// the dialog
+			CUissCmdHandler* cmdHandler=UissCmdHandlerFactoryL(err);
+			if (!cmdHandler)
+				{
+				User::Leave(KErrNotSupported);
+				}
+			
+			CleanupStack::PushL(cmdHandler);
+			// Note that the callback might call CancelOperation which
+			// would update iState...
+			cmdHandler->HandleMessageL(iPtrIntoBuf, iPtrIntoBuf);
+			CleanupStack::PopAndDestroy(cmdHandler);
+			}
+		else
+			{
+			#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+			// Request has been completed successfully. So, now construct the 
+			// component info from the buffer which is populated from the SWI server.
+			if (err == KErrNone  && iState == KUissClientGettingCompInfo)
+				{
+				ConstructCompInfoFromBufferL();
+				}			
+			#endif
+			// Either KErrNone or some sort of error status - in any case the processing has finished
+			iState = KUissClientIdle;			
+			}
+		}
+	
+	// Re-issue request, if we are still installing/uninstalling
+	switch(iState)
+		{
+	case KUissClientInstalling:
+	case KUissClientUninstalling:
+		iUissSession.CompleteDialog(KErrNone, iPtrIntoBuf, iStatus);
+		if (iActiveObjectMode)
+			{
+			SetActive();
+			}
+		return;
+			
+	case KUissClientIdle:
+		// All done, or failed...
+		delete iArgsStream;
+		iArgsStream = 0;
+		//Wait for the death of SisHelper
+		WaitForSisHelperShutdown();	
+		// Complete user request (also sets iClientStatus to 0)
+		ASSERT(iClientStatus);
+		User::RequestComplete(iClientStatus, err);
+		return;
+		}
+	ASSERT(false);
+    }
+
+
+TInt CUissClientHandler::RunError(TInt aError)
+	{
+	DEBUG_PRINTF2(_L8("Sis Helper - UISS Client Handler, RunError. Error: %d."), aError);
+	// Pass failure code on to our client.
+	iPtrIntoBuf.Zero();
+	iUissSession.CompleteDialog(aError, iPtrIntoBuf, iStatus);
+    if (iActiveObjectMode)
+		{
+		SetActive();
+		}
+	return KErrNone; // Do not crash the CActiveScheduler.
+	}
+
+void CUissClientHandler::DoCancel()
+    {
+    DEBUG_PRINTF(_L8("Sis Helper - UISS Client Handler, Cancelling."));
+    
+	// Normally NEVER called because the application should have
+	// waited for the original request to complete!
+	
+	// We can NOT simply call CancelOperation, because when we return
+	// into the framework Cancel function it will block on our
+	// iStatus, which would stop the active scheduler and hence stop
+	// the CancelOperation from being actioned.
+
+	// Do an emergency abort.....
+
+	// First kill our helper threads
+	
+	// SIS helper thread/server
+	CSisHelperServer::Abort();
+	
+	// UI helper thread/server
+	TFullName fullName = RProcess().FullName();
+	fullName.Append(':');
+	fullName.Append(':');
+	fullName.Append(KUissServerName);
+
+	RThread server;
+	TInt err = server.Open(fullName);
+	if (err == KErrNone)
+		{
+		server.Terminate(KErrAbort);
+		server.Close();
+		}
+	
+	// Now complete any client request
+	if (iClientStatus)
+		{
+		User::RequestComplete(iClientStatus, err);
+		}
+    }
+    
+#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+void CUissClientHandler::ConstructCompInfoFromBufferL()
+    {    
+    // create a stream based on the buffer
+	RDesReadStream stream(*iCompInfoBuffer);
+	CleanupClosePushL(stream);
+	
+	CNativeComponentInfo* nativeCompInfo = CNativeComponentInfo::NewLC();
+	nativeCompInfo->InternalizeL(stream);
+		
+	// 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),
+	// which is returned by SWI and is converted here to the CComponentInfo according to the USIF interface
+	Usif::CComponentInfo::CNode* rootNode = MapToComponentInfoL(*nativeCompInfo);
+	iComponentInfo->SetRootNodeL(rootNode);
+
+	CleanupStack::PopAndDestroy(nativeCompInfo);
+	CleanupStack::PopAndDestroy(&stream);
+    }
+
+Usif::CComponentInfo::CNode* CUissClientHandler::MapToComponentInfoL(CNativeComponentInfo& aNativeComponentInfo)
+	{
+	// Create the array to store the children nodes.
+	RPointerArray<Usif::CComponentInfo::CNode> children;
+	CleanupResetAndDestroyPushL(children);
+	
+	// If there is any child for the current node, call this method with that child object.
+	// Continue this (recursively) until we get the leaf node in the embedded tree (with no children)
+	// and add the resultant node as one of the children and pass it to create the parent node further.
+	TInt count = aNativeComponentInfo.iChildren.Count();
+	for (TInt i = 0; i < count; ++i)
+		{
+		Usif::CComponentInfo::CNode* node = MapToComponentInfoL(*aNativeComponentInfo.iChildren[i]);
+		CleanupStack::PushL(node);
+		children.AppendL(node);
+		CleanupStack::Pop(node);
+		}
+		
+	// Create the CNode object using the appropriate parameters.
+	// children for leaf nodes (bottom most nodes in the embedded tree) will be null.
+	Usif::CComponentInfo::CNode* node = Usif::CComponentInfo::CNode::NewLC(
+										Usif::KSoftwareTypeNative(),
+										*(aNativeComponentInfo.iComponentName), 
+										*(aNativeComponentInfo.iVersion),
+										*(aNativeComponentInfo.iVendor),
+										static_cast<Usif::TScomoState>(aNativeComponentInfo.iScomoState),
+										static_cast<Usif::TInstallStatus>(aNativeComponentInfo.iInstallStatus),
+										aNativeComponentInfo.iComponentId,
+										*(aNativeComponentInfo.iGlobalComponentId),
+										static_cast<Usif::TAuthenticity>(aNativeComponentInfo.iAuthenticity),
+										aNativeComponentInfo.iUserGrantableCaps,
+										aNativeComponentInfo.iMaxInstalledSize,
+										aNativeComponentInfo.iHasExe,
+										&children);
+	CleanupStack::Pop(node);
+	CleanupStack::Pop(&children);
+	children.Close();
+	return (node);
+	}
+#endif
+} // namespace Swi