|
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(¶mPckg)); |
|
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(¶mPckg)); |
|
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(¶mPckg)); |
|
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 |