commsprocess/commsrootserverconfig/rootsrv/c32root.cpp
changeset 0 dfb7c4ff071f
equal deleted inserted replaced
-1:000000000000 0:dfb7c4ff071f
       
     1 // Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 /**
       
    17  @file
       
    18  @publishedPartner
       
    19  @released
       
    20 */
       
    21 
       
    22 #include <c32root.h>
       
    23 #include <comms-infras/commsdebugutility.h>
       
    24 #include <e32property.h>
       
    25 
       
    26 
       
    27 #ifdef _DEBUG
       
    28 // Panic category for "absolutely impossible!" vanilla ASSERT()-type panics from this module
       
    29 // (if it could happen through user error then you should give it an explicit, documented, category + code)
       
    30 _LIT(KSpecAssert_RootSrvc32rootc, "RootSrvc32root.c");
       
    31 #endif
       
    32 
       
    33 __FLOG_STMT(_LIT8(KSubsys,"RootServer");) // subsystem name
       
    34 __FLOG_STMT(_LIT8(KComponent,"event");) // component name
       
    35 static const TInt KMaxKillRetry = 10;
       
    36 
       
    37 
       
    38 EXPORT_C TInt RRootServ::Connect()
       
    39     /** Use this function to open a session to the Root Server.
       
    40     Default number of message slots is defined in KDefaultMessageSlots.
       
    41     As with any server, the connection should be closed after use.
       
    42     RHandleBase provides the necessary Close() function, which should be
       
    43     called when the server session is no longer required.
       
    44     @return An error code
       
    45     @publishedPartner
       
    46     @released
       
    47     */
       
    48     {
       
    49 
       
    50 	__FLOG_DECLARATION_VARIABLE;
       
    51 	__FLOG_OPEN(KSubsys, KComponent);
       
    52     __FLOG_1(_L("RRootServ::Connect: client %d"), (TUint) RThread().Id());
       
    53 
       
    54     TInt r = CreateSession(KRootServerName, Version());
       
    55 
       
    56 	__FLOG_CLOSE;
       
    57     return r;
       
    58     }
       
    59 
       
    60 EXPORT_C TVersion RRootServ::Version() const
       
    61     /** Returns the client side version number.
       
    62     Use this function to get the version number. The version number may be
       
    63     incremented in future releases of the Root Server. If extra features are
       
    64     added in such releases, the version number may be used by application programs
       
    65     as a basis for assessing the capabilities of the Root Server.
       
    66     @return version number
       
    67     @publishedPartner
       
    68     @released
       
    69     */
       
    70     {
       
    71     return(TVersion(KRS32MajorVersionNumber,KRS32MinorVersionNumber,KRS32BuildVersionNumber));
       
    72     }
       
    73     
       
    74 EXPORT_C TBool RRootServ::IsCallerConfigurationAuthority() const
       
    75 	/** Tests whether the calling process is deemed to be the RootServer Configurator. While
       
    76 	multiple instances of the configurator process may connect only the first (at one time) can
       
    77 	take the role of being the authority for configuration; others might watch but should not
       
    78 	take action.
       
    79     @return True if the calling process is deemed to be the RootServer Configurator. 
       
    80     @internalTechnology
       
    81     @released
       
    82 	*/
       
    83 	{
       
    84     return SendReceive(RSIsCallerConfigurator) > 0;
       
    85 	}    
       
    86 
       
    87 EXPORT_C TInt RRootServ::SetMBufPoolSize(TUint aPoolSize)
       
    88     /** Set the size of the MBuf pool.
       
    89     This function can only be called before the first server module is loaded.
       
    90     @param aPoolSize Defines the new size of the Comms buffer pool in number of bytes.
       
    91     @return An error code.
       
    92     @publishedPartner
       
    93     @released
       
    94     @capability NetworkControl The Security ID of the caller will be checked to ensure that
       
    95     this request came from the comms configurator
       
    96     */
       
    97     {
       
    98     TRSSetMBufMnr paramPckg;
       
    99     TRSSetMBufMnrContainer &container = paramPckg();
       
   100     container.iInitSize = aPoolSize;
       
   101     container.iMaxSize = aPoolSize;
       
   102 
       
   103     return SendReceive(RSSetMBufPoolSize, TIpcArgs(&paramPckg));
       
   104     }
       
   105 
       
   106 
       
   107 EXPORT_C TInt RRootServ::SetMBufPoolSize(TUint aInitPoolSize, TUint aMaxPoolSize)
       
   108  /** Set the size of the MBuf pool.
       
   109     This function can only be called before the first server module is loaded.
       
   110     @param aInitPoolSize Defines the initial size of the new Comms Buffer Pool
       
   111     @param aInitPoolSize Defines the maximum size of the new Comms Buffer Pool can grow to
       
   112     @return An error code.
       
   113     @publishedPartner
       
   114     @released
       
   115     @capability NetworkControl The Security ID of the caller will be checked to ensure that
       
   116     this request came from the comms configurator
       
   117     */
       
   118     {
       
   119     TRSSetMBufMnr paramPckg;
       
   120     TRSSetMBufMnrContainer &container = paramPckg();
       
   121     container.iInitSize = aInitPoolSize;
       
   122     container.iMaxSize = aMaxPoolSize;
       
   123 
       
   124     return SendReceive(RSSetMBufPoolSize, TIpcArgs(&paramPckg));
       
   125     }
       
   126 
       
   127 EXPORT_C TInt RRootServ::AddMBufAllocInfo(const TRSAddMBufAllocInfoContainer& aMBufSizeAllocInfo)
       
   128 /** Adds information to the MBufManager about how it should allocate MBufs of a given.
       
   129     @param aMBufSizeAllocInfo defines the mbuf size alloc info
       
   130     @return An error code.
       
   131     @internalTechnology
       
   132     @capability NetworkControl The Security ID of the caller will be checked to ensure that
       
   133     this request came from the comms configurator
       
   134     */
       
   135  	{
       
   136     TRSAddMBufAllocInfo paramPckg;
       
   137     TRSAddMBufAllocInfoContainer &container = paramPckg();
       
   138     container  = aMBufSizeAllocInfo;
       
   139 
       
   140     return SendReceive(RSAddMBufAllocInfo, TIpcArgs(&paramPckg));
       
   141 	}
       
   142 
       
   143 EXPORT_C void RRootServ::LoadCpm(TRequestStatus& aStatus,
       
   144                                  const TRSStartModuleParams& aParams, const TDesC8& aIniData)
       
   145     /** Launch a new Comms Provider Module.
       
   146     The name of the new CPM instance (aParams.iParams.iName) must be unique and must
       
   147     be used in any further communication concerning this CPM instance, such as binding.
       
   148     The contents of the initialisation data parameter (aIniData) are specific to the module.
       
   149     It could be empty, contain the contents of an associated INI file or contain some other
       
   150     data specified by the specific CPM implementation.
       
   151     Attempts to load a CPM with a name equal to that of an existing CPM is not possible.
       
   152     It is required that the DLL contains the CPM secondary UID of 0x101f7418.
       
   153     @param aStatus The request status used to contain completion information for the function.
       
   154     @param aParams Parameters needed to load the Provider Module.
       
   155     @param aIniData Module specific ini data.
       
   156     @see TRSStartModuleParams
       
   157     @publishedPartner
       
   158     @released
       
   159     @capability NetworkControl The Security ID of the caller will be checked to ensure that
       
   160     this request came from the comms configurator
       
   161     */
       
   162     {
       
   163     SendReceive(RSLoadModule, TIpcArgs(&aParams, &aIniData), aStatus);
       
   164     }
       
   165 
       
   166 EXPORT_C void RRootServ::UnloadCpm(TRequestStatus& aStatus, const TCFModuleName& aName, TRSUnLoadType aType)
       
   167     /** Unloads a Comms Provider Module.
       
   168     @param aStatus The request status used to contain completion information for the function.
       
   169     @param aName Name of module to unload
       
   170 	@param aType Type of unload (optional/graceful/ungraceful).
       
   171 	@see TCFModuleName
       
   172 	@see TRSUnLoadType
       
   173 	@publishedPartner
       
   174     @released
       
   175     @capability NetworkControl The Security ID of the caller will be checked to ensure that
       
   176     this request came from the comms configurator
       
   177     */
       
   178     {
       
   179     SendReceive(RSUnloadModule, TIpcArgs(&aName, aType), aStatus);
       
   180     }
       
   181 
       
   182 EXPORT_C void RRootServ::SendMessage(TRequestStatus& aStatus, const TCFModuleName& aName, TInt aType, TDes8& aData)
       
   183 	/**
       
   184 	Sends a message to the module
       
   185 	@param aStatus The request status used to contain completion information for the function.
       
   186 	@param aType a type determining the type of data in aData param
       
   187 	@param aData a data specific to the message and it's type given by aType. All aData is expected to be
       
   188 			CNetMessage based serialised instance
       
   189 	@see TCFMessageType for message/data types supported by ESOCK directly
       
   190 	@see CNetMessage
       
   191 	*/
       
   192 	{
       
   193    SendReceive(RSSendMessage, TIpcArgs(&aName, aType, &aData), aStatus);
       
   194 	}
       
   195 
       
   196 EXPORT_C TInt RRootServ::SendMessage(const TCFModuleName& aName, TInt aType, TDes8& aData)
       
   197 	/**
       
   198 	Sends a message to the module
       
   199 	@param aStatus The request status used to contain completion information for the function.
       
   200 	@param aType a type determining the type of data in aData param
       
   201 	@param aData a data specific to the message and it's type given by aType. All aData is expected to be
       
   202 			CNetMessage based serialised instance
       
   203 	@see TCFMessageType for message/data types supported by ESOCK directly
       
   204 	@see CNetMessage
       
   205 	*/
       
   206 	{
       
   207    return SendReceive(RSSendMessage, TIpcArgs(&aName, aType, &aData));
       
   208 	}
       
   209 
       
   210 EXPORT_C void RRootServ::Bind(TRequestStatus& aStatus, TRSBindingInfo& aBindInfo)
       
   211     /** Binds two modules.
       
   212     Several types of binding are available: EHierarchical is the standard top-bottom
       
   213     binding in the protocol hierarchy. If this type is specified, iName1 of TRSBindingInfo is considered top-level
       
   214     module of the binding and iName2 is considered the bottom-level part. Also, this type of binding
       
   215     allows the top-level module to be a server. ECustom is a "Horizontal" binding between two CPM's.
       
   216     Typical use is when a CPM employs another CPM for doing some processing and communicates via the
       
   217     standard message queues.
       
   218     @param aStatus The request status used to contain completion information for the function.
       
   219     @param aBindInfo The information regarding the binding request.
       
   220     @see TRSBindingInfo
       
   221     @publishedPartner
       
   222     @released
       
   223     @capability NetworkControl The Security ID of the caller will be checked to ensure that
       
   224     this request came from the comms configurator */
       
   225     {
       
   226     SendReceive(RSBind, TIpcArgs(&aBindInfo), aStatus);
       
   227 	}
       
   228 
       
   229 EXPORT_C void RRootServ::Unbind(TRequestStatus& aStatus, TRSUnBindingInfo& aUnBindInfo)
       
   230     /** Unbinds two modules.
       
   231     All bindings between the two modules are unbound and the states for each module
       
   232     are updated in the object.
       
   233     @param aStatus The request status used to contain completion information for the function.
       
   234     @param aUnBindInfo Holds the unbinding info.
       
   235     @see TRSUnBindingInfo
       
   236     @publishedPartner
       
   237     @released
       
   238     @capability NetworkControl The Security ID of the caller will be checked to ensure that
       
   239     this request came from the comms configurator
       
   240     */
       
   241     {
       
   242     SendReceive(RSUnbind, TIpcArgs(&aUnBindInfo), aStatus);
       
   243     }
       
   244 
       
   245 EXPORT_C TInt RRootServ::GetModuleInfo(const TCFModuleName& aName, TRSModuleInfo& aModuleInfo)
       
   246     /** Gets information about one module.
       
   247     @param aName Name of module to query.
       
   248     @param aModuleInfo Information about the module state.
       
   249     @see TCFModuleName
       
   250     @see TRSModuleInfo
       
   251     @return An error code.
       
   252     @publishedPartner
       
   253     @released
       
   254     */
       
   255     {
       
   256     return SendReceive(RSGetModuleInfo, TIpcArgs(&aName, &aModuleInfo));
       
   257     }
       
   258 
       
   259 EXPORT_C TInt RRootServ::EnumerateModules(TRSIter &aPosition, TCFModuleName& aModuleName)
       
   260     /** Through repeated calls returns the list of names of running Comms Provider Modules.
       
   261     Notes:
       
   262 	- The current position in an enumeration is maintained for each client session, meaning that
       
   263 	  to perform two consecutive enumerations two RRootServ's must be used.
       
   264 	- The order in which the modules are returned is undefined.
       
   265 	- The enumeration returned is not a snapshot from the start, i.e. if modules are loaded or
       
   266 	  unloaded during the enumeration then a module could be skipped or returned twice.
       
   267     @param aPosition Position in enumeration.
       
   268     @param aName Contains module upon successful return.
       
   269     @return An error code: KErrNone upon success, KErrEOF upon reaching the end of the enumeration.
       
   270     @see TRSIter
       
   271     @see TCFModuleName
       
   272     @publishedPartner
       
   273     @released
       
   274     */
       
   275     {
       
   276 	TPckg<TRSIter> pkgPos(aPosition);
       
   277     return SendReceive(RSEnumerateModules, TIpcArgs(&pkgPos, &aModuleName));
       
   278     }
       
   279 
       
   280 EXPORT_C TInt RRootServ::EnumerateSubModules(const TCFModuleName& aModuleName, TRSIter &aPosition, TCFSubModuleName& aSubModuleName)
       
   281     /** Returns a list of running Comms Provider Modules.
       
   282     The client can enumerate sub-modules one at a time by providing a TCFSubModuleName.
       
   283     The enumerator aPosition is a correlator for Rootserver use.
       
   284     @param aModuleName Name of module.
       
   285     @param aPosition Position in enumeration, correlator for the Rootserver.
       
   286     @param aSubModuleName A name to be returned
       
   287     @return An error code.
       
   288     @see TCFModuleName
       
   289     @see TRSIter
       
   290     @see TCFSubModuleName
       
   291     @publishedPartner
       
   292     @released
       
   293     */
       
   294     {
       
   295 	TPckg<TRSIter> pkgPos(aPosition);
       
   296     return SendReceive(RSEnumerateSubModules, TIpcArgs(&aModuleName, &pkgPos, &aSubModuleName));
       
   297     }
       
   298 
       
   299 EXPORT_C TInt RRootServ::EnumerateBindings(const TCFSubModuleAddress& aSubModuleAddr, TRSIter &aPosition, TRSBindingInfo& aBinding)
       
   300     /** Gets information about the bindings on one module.
       
   301 	The client can enumerate bindings one at a time, with
       
   302     the first message specifying the iReset flag (in the TRSEnumerateBindInfo struct) true, and
       
   303     subsequent requests for all bind infos specify this as false, in which case the Root Server will
       
   304     write from where it left off from the last request.
       
   305     @param aSubModuleAddr The address of the SubModule in question
       
   306     @param aPosition Position in enumeration. Correlator for the Rootserver.
       
   307     @param aBinding On succesful return contains binding information.
       
   308     @return An error code.
       
   309     @see TCFSubModuleAddress
       
   310     @see TRSIter
       
   311     @see TRSBindingInfo
       
   312     @publishedPartner
       
   313     @released
       
   314     */
       
   315     {
       
   316 	TPckg<TRSIter> pkgPos(aPosition);
       
   317 	TRSSubModuleAddress pckgSubModuleAddr(aSubModuleAddr);
       
   318     return SendReceive(RSEnumerateBindings, TIpcArgs(&pckgSubModuleAddr, &pkgPos, &aBinding));
       
   319     }
       
   320 
       
   321 EXPORT_C void RRootServ::CancelLoadCpm(const TCFModuleName& aName)
       
   322     /** Cancels asynchronous loading of a comms Provider Module.
       
   323     There is no guarantee the module loading is canceled.
       
   324     A best effort is made and the asynchronous request waiting for
       
   325     the module to load returns with KErrCanceled on success.
       
   326     @param aName Name of module which is loading.
       
   327     @see TCFModuleName
       
   328     @publishedPartner
       
   329     @released
       
   330     */
       
   331     {
       
   332     (void)SendReceive(RSCancelLoadModule, TIpcArgs(&aName));
       
   333     }
       
   334 
       
   335 EXPORT_C void RRootServ::CancelUnloadCpm(const TCFModuleName& aName)
       
   336     /** Cancel asynchronous unloading of a comms Provider Module.
       
   337     There is no guarantee the module unloading is canceled.
       
   338     A best effort is made and the asynchronous request waiting for
       
   339     the module to load returns KErrCanceled on success.
       
   340     @param aName Name of module which is unloading.
       
   341     @see TCFModuleName
       
   342     @publishedPartner
       
   343     @released
       
   344     */
       
   345     {
       
   346     (void)SendReceive(RSCancelUnloadModule, TIpcArgs(&aName));
       
   347     }
       
   348 
       
   349 EXPORT_C void RRootServ::CancelBind(TRSSubModuleAddress& aName1, TRSSubModuleAddress& aName2)
       
   350     /** Cancels asynchronous binding of two modules.
       
   351     There is no guarantee the binding is canceled.
       
   352     A best effort is made and the asynchronous request waiting for
       
   353     the module to load returns KErrCanceled on success.
       
   354     @param aName1 Name of module which is binding to aName2.
       
   355     @param aName2 Name of module which is binding to aName1.
       
   356     @see TRSSubModuleAddress
       
   357     @publishedPartner
       
   358     @released
       
   359     */
       
   360     {
       
   361     (void)SendReceive(RSCancelBind, TIpcArgs(&aName1, &aName2));
       
   362     }
       
   363 
       
   364 EXPORT_C void RRootServ::CancelUnbind(TRSSubModuleAddress& aName1, TRSSubModuleAddress& aName2)
       
   365     /** Cancels asynchronous unbinding of two modules.
       
   366     There is no guarantee the unbinding is canceled.
       
   367     A best effort is made and the asynchronous request waiting for
       
   368     the module to load returns KErrCanceled on success.
       
   369     @param aName1 Name of module which is unbinding from aName2.
       
   370     @param aName2 Name of module which is unbinding from aName1.
       
   371     @see TRSSubModuleAddress
       
   372     @publishedPartner
       
   373     @released
       
   374     */
       
   375     {
       
   376     (void)SendReceive(RSCancelUnbind, TIpcArgs(&aName1, &aName2));
       
   377     }
       
   378 
       
   379 EXPORT_C TInt RRootServ::Shutdown()
       
   380 	/** Shuts down RootServer
       
   381 	@publishedPartner
       
   382     @released
       
   383     @capability NetworkControl The Security ID of the caller will be checked to ensure that
       
   384     this request came from the comms configurator
       
   385     */
       
   386 	{
       
   387 	return SendReceive(RSShutdown);
       
   388 	}
       
   389 
       
   390 EXPORT_C void RRootServ::Close()
       
   391 	/** Tells server that this session is being closed
       
   392  	@publishedPartner
       
   393     @released
       
   394      */
       
   395     {
       
   396     (void)SendReceive(RSCloseSession);
       
   397 	RHandleBase::Close();
       
   398     }
       
   399 
       
   400 #if defined (_DEBUG_ROOTSERVER_FUNCTIONS)
       
   401 EXPORT_C TInt RRootServ::__DbgMarkHeap()
       
   402 	/** Sets a heap mark in the root server
       
   403 	@internalComponent
       
   404     */
       
   405 	{
       
   406 	return SendReceive(RSDbgMarkHeap,TIpcArgs());
       
   407 	}
       
   408 
       
   409 EXPORT_C TInt RRootServ::__DbgCheckHeap(TInt aCount)
       
   410 	/** Sets a heap mark in the root server
       
   411 	@internalComponent
       
   412     */
       
   413 	{
       
   414 	return SendReceive(RSDbgCheckHeap,TIpcArgs(aCount));//check if it's right
       
   415 	}
       
   416 
       
   417 EXPORT_C TInt RRootServ::__DbgMarkEnd(TInt aCount)
       
   418 	/** Sets a heap mark in the root server
       
   419 	@internalComponent
       
   420     */
       
   421 	{
       
   422 	return SendReceive(RSDbgMarkEnd,TIpcArgs(aCount));//check if it's right
       
   423 	}
       
   424 EXPORT_C TInt RRootServ::__DbgFailNext(TInt aCount)
       
   425 	/** Sets a heap mark in the root server
       
   426 	@internalComponent
       
   427     */
       
   428 	{
       
   429 	return SendReceive(RSDbgFailNext,TIpcArgs(aCount));//check if it's right
       
   430 	}
       
   431 
       
   432 EXPORT_C TInt RRootServ::__DbgFailNextMbuf(TInt aCount)
       
   433 	/** Sets a Mbuf mark in the root server
       
   434 	@internalComponent
       
   435     */
       
   436 	{
       
   437 	return SendReceive(RSDbgFailNextMbuf,TIpcArgs(aCount));//check if it's right
       
   438 	}
       
   439 
       
   440 EXPORT_C TInt RRootServ::__DbgSetMbufPoolLimit(TInt aSize)
       
   441 	/** Sets the Mbuf pool limit
       
   442 	@internalComponent
       
   443     */
       
   444 	{
       
   445 	return SendReceive(RSDbgSetMbufPoolLimit,TIpcArgs(aSize));//check if it's right
       
   446 	}
       
   447 
       
   448 EXPORT_C TInt RRootServ::__DbgCheckMbuf(TInt aSize)
       
   449 	/** Sets the Mbuf pool limit
       
   450 	@internalComponent
       
   451     */
       
   452 	{
       
   453 	return SendReceive(RSDbgCheckMbuf,TIpcArgs(aSize));//check if it's right
       
   454 	}
       
   455 
       
   456 EXPORT_C TInt RRootServ::__DbgMbufFreeSpace()
       
   457 	/** Gets the amount of free space in the MBuf manager
       
   458 	@internalComponent
       
   459     */
       
   460 	{
       
   461 	TPckgBuf<TInt> i;
       
   462 	TInt result=SendReceive(RSDbgMbufFreeSpace,TIpcArgs(&i));
       
   463 	if (KErrNone == result)
       
   464 		{
       
   465 		return i();
       
   466 		}
       
   467 	else
       
   468 		{
       
   469 		return result;
       
   470 		}
       
   471 	}
       
   472 
       
   473 EXPORT_C TInt RRootServ::__DbgMbufTotalSpace()
       
   474 	/** Gets the amount of free space in the MBuf manager
       
   475 	@internalComponent
       
   476     */
       
   477 	{
       
   478 	TPckgBuf<TInt> i;
       
   479 	TInt result = SendReceive(RSDbgMbufTotalSpace,TIpcArgs(&i));
       
   480 	if (KErrNone == result)
       
   481 		{
       
   482 		return i();
       
   483 		}
       
   484 	else
       
   485 		{
       
   486 		return result;
       
   487 		}
       
   488 	}
       
   489 #else
       
   490 EXPORT_C TInt RRootServ::__DbgMarkHeap()
       
   491 	/** Sets a heap mark in the root server
       
   492 	@internalComponent
       
   493     */
       
   494 	{
       
   495 	return KErrNone;
       
   496 	}
       
   497 
       
   498 EXPORT_C TInt RRootServ::__DbgCheckHeap(TInt /*aCount*/)
       
   499 	/** Sets a heap mark in the root server
       
   500 	@internalComponent
       
   501     */
       
   502 	{
       
   503    return KErrNone;
       
   504 	}
       
   505 
       
   506 EXPORT_C TInt RRootServ::__DbgMarkEnd(TInt /*aCount*/)
       
   507 	/** Sets a heap mark in the root server
       
   508 	@internalComponent
       
   509     */
       
   510 	{
       
   511    return KErrNone;
       
   512 	}
       
   513 EXPORT_C TInt RRootServ::__DbgFailNext(TInt /*aCount*/)
       
   514 	/** Sets a heap mark in the root server
       
   515 	@internalComponent
       
   516     */
       
   517 	{
       
   518    return KErrNone;
       
   519 	}
       
   520 
       
   521 EXPORT_C TInt RRootServ::__DbgFailNextMbuf(TInt /*aCount*/)
       
   522 	/** Sets a Mbuf mark in the root server
       
   523 	@internalComponent
       
   524     */
       
   525    {
       
   526    return KErrNone;
       
   527 	}
       
   528 
       
   529 EXPORT_C TInt RRootServ::__DbgSetMbufPoolLimit(TInt /*aSize*/)
       
   530 	/** Sets the Mbuf pool limit
       
   531 	@internalComponent
       
   532     */
       
   533    {
       
   534    return KErrNone;
       
   535 	}
       
   536 
       
   537 EXPORT_C TInt RRootServ::__DbgCheckMbuf(TInt /*aSize*/)
       
   538 	/** Sets the Mbuf pool limit
       
   539 	@internalComponent
       
   540     */
       
   541    {
       
   542    return KErrNone;
       
   543 	}
       
   544 
       
   545 EXPORT_C TInt RRootServ::__DbgMbufFreeSpace()
       
   546 	/** Gets the amount of free space in the MBuf manager
       
   547 	@internalComponent
       
   548     */
       
   549    {
       
   550    return KErrNone;
       
   551 	}
       
   552 
       
   553 EXPORT_C TInt RRootServ::__DbgMbufTotalSpace()
       
   554 	/** Gets the amount of free space in the MBuf manager
       
   555 	@internalComponent
       
   556     */
       
   557    {
       
   558    return KErrNone;
       
   559 	}
       
   560 #endif // _DEBUG
       
   561 
       
   562 
       
   563 static TInt DoStartC32(const TDesC& aCMISuppressionList, const TRSStartState aFinishedState)
       
   564     /** Starts the Root Server and the c32start.exe example configuration program.
       
   565     Any caller of this function is blocked until the Root Server is
       
   566     fully loaded and configured by the example configuration utility: c32start.exe.
       
   567     This is because any call expects that it can instantly use networking
       
   568     services offered by the modules loaded during configuration.
       
   569     return An error code.
       
   570     @publishedPartner
       
   571     @released
       
   572     */
       
   573     {
       
   574 
       
   575 	__FLOG_DECLARATION_VARIABLE;
       
   576 	__FLOG_OPEN(KSubsys, KComponent);
       
   577 	__FLOG_1(_L("DoStartC32(\"%S\")"), &aCMISuppressionList);
       
   578 
       
   579     TInt propertyResult = KErrNone;
       
   580     
       
   581 	// Four possibilities exist at this point:
       
   582 	//	(1) C32Start has not yet been created
       
   583 	//	(2) C32Start has been created but has yet to define the start property key
       
   584 	//	(3) C32Start has defined the key but its state hasn't yet reached "core components started"
       
   585 	//	(4) Boot is past "core components started" and we can return control to our caller    
       
   586 	RProperty configurationProperty;
       
   587 	TInt propertyValue = EInitialising;	// set to safe state
       
   588 	TInt result = configurationProperty.Attach(KUidSystemCategory, KUidC32StartPropertyKey.iUid);	
       
   589 	if(result == KErrNone)
       
   590 		{
       
   591 		result = configurationProperty.Get(propertyValue);
       
   592 		}
       
   593 
       
   594 	if(result!=KErrNone || propertyValue==EReset)
       
   595 		{
       
   596 		RProcess C32Start;
       
   597 		result = C32Start.Create(KCommC32StartExe, aCMISuppressionList);
       
   598 
       
   599 		if (result == KErrNone)
       
   600 			{
       
   601 			__FLOG(_L("StartC32 - Starting C32Start.exe"));
       
   602 			TRequestStatus status;
       
   603 			C32Start.Rendezvous(status);
       
   604 			C32Start.Resume();
       
   605 			__FLOG(_L("StartC32 - waiting for C32Start.exe to complete init."));
       
   606 
       
   607 			User::WaitForRequest(status);
       
   608 			// we are not worried about the rendezvous status, as we only wait on it
       
   609 			// so that we know there is a property we can subscribe to below.  Basically
       
   610 			// we should either get KErrAlreadyExists, or KErrNone, but either way we
       
   611 			// have a property to subscribe to, so everything is ok.
       
   612 
       
   613 			// Now that the configurator has read the suppression list we delete to avoid persistent settings between
       
   614 			// different startups
       
   615 			}
       
   616 		else if (result == KErrAlreadyExists)
       
   617 			{
       
   618 			result = KErrNone;
       
   619 			}
       
   620  		// In case of missing c32start.exe the error code is returned to avoid silent deadlock
       
   621  		else if (result != KErrNone) 
       
   622  			{
       
   623  			C32Start.Close();
       
   624  			return result;
       
   625 			}
       
   626 
       
   627 		// for the case where C32 might already be in the process of starting up
       
   628 		// we use a double-check-type pattern to ensure the property has been
       
   629 		// published before we try and use it
       
   630 
       
   631 		propertyResult = configurationProperty.Get(propertyValue);
       
   632 
       
   633 		if(propertyResult != KErrNone)
       
   634 			{
       
   635 			TRequestStatus status;
       
   636 			C32Start.Rendezvous(status);
       
   637 			propertyResult = configurationProperty.Get(propertyValue);
       
   638 
       
   639 			if(propertyResult == KErrNone)
       
   640 				{
       
   641 				C32Start.RendezvousCancel(status);
       
   642 				}
       
   643 			User::WaitForRequest(status);
       
   644 			}
       
   645 		C32Start.Close();
       
   646 		}
       
   647 
       
   648 	// we have a property and have a value now lets check the value.
       
   649 	// If it is EConfigured then we are done, and can return to the waiting client
       
   650 	// however, if it is not yet at level aFinishedState, then we have to wait for the
       
   651 	// property value to change, by subscribing to it, and doing a synchronous wait.  If the
       
   652 	// Get() fails, then we assume something went wrong, and return the error to the client!
       
   653 	TRequestStatus propertyStatus = KErrNone;
       
   654 
       
   655 	while(propertyStatus == KErrNone && propertyValue < aFinishedState)
       
   656 		{
       
   657 		__FLOG_1(_L("StartC32 - Published configuration sequence is %d."), propertyValue);
       
   658 		configurationProperty.Subscribe(propertyStatus);
       
   659 
       
   660 		if(configurationProperty.Get(propertyValue) == KErrNone && propertyValue>= aFinishedState)
       
   661 			{
       
   662 			__FLOG(_L("StartC32 - Cancelling subscription."));
       
   663 			configurationProperty.Cancel();
       
   664 			User::WaitForRequest(propertyStatus);	// absorb signal
       
   665 			__FLOG(_L("StartC32 - Absorbed signal."));
       
   666 			break;
       
   667 			}
       
   668 		User::WaitForRequest(propertyStatus);
       
   669 		}
       
   670 
       
   671 	__FLOG_1(_L("StartC32 - Published configuration sequence is %d."), propertyValue);
       
   672 	__ASSERT_DEBUG(result == KErrNone && propertyResult == KErrNone, User::Panic(KSpecAssert_RootSrvc32rootc, 1)); // if it isn't defined then either C32Start didn't define the property before rendezvousing or PubSub went wrong
       
   673 	configurationProperty.Close();
       
   674 	__FLOG(_L("StartC32 - Root Server configured"));
       
   675 
       
   676 	__FLOG_CLOSE;
       
   677     return result;
       
   678     }
       
   679 
       
   680 EXPORT_C TInt StartC32()
       
   681     /** Start the Root Server and the c32start.exe example configuration program.
       
   682     Any caller of this function is blocked until the Root Server is
       
   683     fully loaded and configured by the example configuration utility: c32start.exe.
       
   684     This is because any called expects that it can instantly use networking
       
   685     services offered by the modules loaded during configuration.
       
   686     return TInt - An error code.
       
   687     @publishedPartner
       
   688     @released
       
   689     */
       
   690     {
       
   691 	// Start with all CMI's enabled
       
   692 	return DoStartC32(KNullDesC, ECoreComponentsStarted);
       
   693     }
       
   694 
       
   695 EXPORT_C TInt StartC32WithCMISuppressions(const TDesC& aCMISuppressionList)
       
   696     /** Start the Root Server and the c32start.exe example configuration program,
       
   697 	supplying a list of CMI files that must not be processed. This functionality is
       
   698 	provided expressly for the ease of legacy testing.
       
   699     Any caller of this function is blocked until the Root Server is
       
   700     fully loaded and configured by the example configuration utility: c32start.exe.
       
   701     This is because any called expects that it can instantly use networking
       
   702     services offered by the modules loaded during configuration.
       
   703     return An error code.
       
   704     @publishedPartner
       
   705     @released
       
   706     */
       
   707     {
       
   708 	return DoStartC32(aCMISuppressionList, ECoreComponentsStarted);
       
   709     }
       
   710 
       
   711 EXPORT_C TInt StartC32Full()
       
   712     /** As StartC32 but doesn't return until c32 is fully up.
       
   713 		
       
   714 	@see StartC32()
       
   715     @internalTechnology
       
   716     */
       
   717     {
       
   718 	// Start with all CMI's enabled
       
   719 	return DoStartC32(KNullDesC, EConfigurationComplete);
       
   720     }
       
   721 
       
   722 EXPORT_C TInt WarmBootC32(const TDesC& aCMISuppressionList)
       
   723     {
       
   724 	__FLOG_DECLARATION_VARIABLE;
       
   725 	__FLOG_OPEN(KSubsys, KComponent);
       
   726 	__FLOG_1(_L("WarmBootC32(\"%S\")"), &aCMISuppressionList);
       
   727 
       
   728 	// Start by looking for the running configurator and kill it if found. The caller
       
   729 	// needs the appropriate capability to do this
       
   730 
       
   731 	__FLOG(_L("Finding existing configurator process."));
       
   732 	_LIT(KC32StartName, "*");
       
   733 	TInt result;
       
   734 	TBool configuratorWasPresent;
       
   735 	TInt count = 0;
       
   736 	do
       
   737 		{
       
   738 		configuratorWasPresent = EFalse;
       
   739 		TFullName fn;
       
   740 		TFindProcess fp(KC32StartName);
       
   741 		while(fp.Next(fn) == KErrNone)
       
   742 			{
       
   743 			RProcess proc;
       
   744 			result = proc.Open(fn);
       
   745 			if(result == KErrNone)
       
   746 				{
       
   747 				TUidType type = proc.Type();
       
   748 				if(type[2] == TUid::Uid(KUidC32StartProcess) && proc.ExitType() == EExitPending) 
       
   749 					{
       
   750 					// Kill the existing configurator process.
       
   751 					__FLOG_VA( (_L("Opened existing configurator process \"%S\""), &fn) );
       
   752 					TRequestStatus status;
       
   753 					proc.Logon(status);
       
   754 					proc.Kill(KErrNone);
       
   755 					__FLOG_VA( (_L("Killed process."), &fn) );
       
   756 					User::WaitForRequest(status);
       
   757 					__FLOG_STMT( TExitType exitType = proc.ExitType() );
       
   758 					
       
   759 					// Create a timer in case some other entity holds an open handle on the
       
   760 					// configurator which prevents the kernel from destroying it.  We timeout
       
   761 					// after one second.
       
   762 					TAutoClose<RTimer> timer;
       
   763 					if(timer.iObj.CreateLocal() == KErrNone)
       
   764 						{
       
   765 						// Request destruction notification so we know when it is safe to start
       
   766 						// the process again.
       
   767 						TRequestStatus destructionStatus;
       
   768 						proc.NotifyDestruction(destructionStatus);
       
   769 						proc.Close();
       
   770 					
       
   771 						enum{ KProcessDestructionTimeout = 1000000 };
       
   772   					
       
   773 						TRequestStatus timerStatus;
       
   774 						timer.iObj.After(timerStatus, KProcessDestructionTimeout);
       
   775 						
       
   776 						// Wait for the process to be destroyed or for the timeout.
       
   777 						User::WaitForRequest(destructionStatus, timerStatus);
       
   778 						if(timerStatus.Int() == KRequestPending)
       
   779 							{
       
   780 							timer.iObj.Cancel();
       
   781 							User::WaitForRequest(timerStatus);
       
   782 							}
       
   783 						else
       
   784 							{
       
   785 							User::CancelMiscNotifier(destructionStatus);
       
   786 							User::WaitForRequest(destructionStatus);
       
   787 			
       
   788 							__FLOG_1(_L("Existing configurator process has still not been destroyed after %f.0s"), KProcessDestructionTimeout / 1000000.0);
       
   789 							}
       
   790 						}
       
   791 					else
       
   792 						{
       
   793 						proc.Close();
       
   794 						}
       
   795 
       
   796 					__FLOG_VA( (_L("Process logon completed with %d, exitType %d"), status.Int(), exitType) );
       
   797 					configuratorWasPresent = ETrue;
       
   798 					}
       
   799 				else
       
   800 					{
       
   801 					proc.Close();
       
   802 					}
       
   803 				}
       
   804 			}
       
   805 		} while(configuratorWasPresent && ++count < KMaxKillRetry);
       
   806 
       
   807 		if (count >= KMaxKillRetry)
       
   808 			{
       
   809 			__FLOG(_L("WarmBootC32 - Cannot kill the configurator process, we will try continue and hope all is well"));
       
   810 			}
       
   811 
       
   812 	// Restart the boot sequence from scratch - the configurator reads this.
       
   813 	RProperty::Set(KUidSystemCategory, KUidC32StartPropertyKey.iUid, EReset);
       
   814 	__FLOG_CLOSE;
       
   815 	result=StartC32WithCMISuppressions(aCMISuppressionList);
       
   816 	return result;
       
   817 	}
       
   818 
       
   819