1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies). |
1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies). |
2 // All rights reserved. |
2 // All rights reserved. |
3 // This component and the accompanying materials are made available |
3 // This component and the accompanying materials are made available |
4 // under the terms of the License "Eclipse Public License v1.0" |
4 // under the terms of "Eclipse Public License v1.0" |
5 // which accompanies this distribution, and is available |
5 // which accompanies this distribution, and is available |
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
7 // |
7 // |
8 // Initial Contributors: |
8 // Initial Contributors: |
9 // Nokia Corporation - initial contribution. |
9 // Nokia Corporation - initial contribution. |
10 // |
10 // |
11 // Contributors: |
11 // Contributors: |
12 // |
12 // |
13 // Description: |
13 // Description: |
|
14 // apparc.cpp |
14 // |
15 // |
15 |
16 |
16 #include <apparc.h> // stuff everyone will want ie most things |
17 #include <apparc.h> // stuff everyone will want ie most things |
17 #include <apacln.h> // CleanupStack protection for CApaDocument |
18 #include "APADLL.H" // RApaApplication |
18 #include "APADLL.H" // CApaDll CApaExe CApaAppHolder |
|
19 #include "APASTD.H" // Panics etc. |
19 #include "APASTD.H" // Panics etc. |
20 #include <e32uid.h> // KExecutableImageUid |
|
21 |
20 |
22 #include <s32stor.h> |
21 |
23 #include <s32file.h> |
22 // |
24 #include <s32std.h> |
23 // RApaApplication |
|
24 // |
25 |
25 |
26 #ifdef USING_ECOM_RECOGS |
26 RApaApplication::RApaApplication() : iApplication(NULL), iScheduledForDeletion(EFalse) |
27 #include <ecom/ecom.h> |
27 {} |
28 #include <ecom/implementationinformation.h> |
|
29 #endif |
|
30 |
28 |
31 #include "../apparc/TRACE.H" |
29 void RApaApplication::Close() |
32 |
|
33 const TInt KAppProcessArrayGranularity(1); |
|
34 |
|
35 _LIT(KApplicationLocation,"\\sys\\bin\\"); |
|
36 |
|
37 ///////////////////////////// |
|
38 // Doc cleanup method |
|
39 ///////////////////////////// |
|
40 |
|
41 EXPORT_C void TApaDocCleanupItem::DoCleanup(TAny* aPtr) |
|
42 { |
30 { |
43 __ASSERT_ALWAYS(aPtr,Panic(EPanicNoCleanupItem)); |
31 delete this; |
44 TApaDocCleanupItem* cleanup = reinterpret_cast<TApaDocCleanupItem*>(aPtr); |
|
45 __ASSERT_ALWAYS(cleanup->iApaProcess,Panic(EPanicNoCleanupItem));//lint !e613 Possible use of null pointer - Asserted above |
|
46 cleanup->iApaProcess->DestroyDocument(cleanup->iApaDoc); //lint !e613 Possible use of null pointer - Asserted above |
|
47 } |
32 } |
48 |
33 |
49 |
34 RApaApplication::~RApaApplication() |
50 ///////////////////////////// |
|
51 // CApaAppHolder |
|
52 ///////////////////////////// |
|
53 |
|
54 CApaAppHolder::CApaAppHolder() |
|
55 {} |
|
56 |
|
57 |
|
58 CApaAppHolder::~CApaAppHolder() |
|
59 { |
35 { |
60 } |
36 iAppName.Close(); |
61 |
|
62 void CApaAppHolder::UpdateAppsRefToThis() |
|
63 { |
|
64 CApaApplication* app = Application(); |
|
65 __ASSERT_ALWAYS(app,Panic(EPanicNoApplication)); |
|
66 app->iAppHolder = this; //lint !e613 Possible use of null pointer - Asserted above |
|
67 } |
|
68 |
|
69 #ifdef USING_ECOM_RECOGS |
|
70 ///////////////////////////// |
|
71 // CApaExe |
|
72 ///////////////////////////// |
|
73 |
|
74 CApaExe::CApaExe() |
|
75 {} |
|
76 |
|
77 CApaExe::~CApaExe() |
|
78 { |
|
79 delete iAppName; |
|
80 delete iApplication; |
37 delete iApplication; |
81 } |
38 } |
82 |
39 |
83 TFileName CApaExe::FileName()const |
40 void RApaApplication::CreateApplicationL(TApaApplicationFactory aApplicationFactory) |
84 { |
41 { |
85 if (iAppName) |
42 __ASSERT_ALWAYS(!iApplication, Panic(EPanicApplicationAlreadyExists)); |
86 { |
43 iApplication = aApplicationFactory.CreateApplicationL(); |
87 return *iAppName; |
44 User::LeaveIfNull(iApplication); |
88 } |
45 |
89 else |
46 iFileUid = aApplicationFactory.AppFileUid(); |
90 { |
47 iAppName.Assign(aApplicationFactory.AppFileNameL()); |
91 return KNullDesC(); |
48 |
92 } |
49 iApplication->SetAppFileNameRef(iAppName); |
93 } |
50 } |
94 |
51 |
95 TUid CApaExe::Uid()const |
52 TFileName RApaApplication::AppFileName() const |
|
53 { |
|
54 return iAppName; |
|
55 } |
|
56 |
|
57 TUid RApaApplication::AppFileUid()const |
96 { |
58 { |
97 return iFileUid; |
59 return iFileUid; |
98 } |
60 } |
99 |
61 |
100 CApaApplication* CApaExe::Application() const |
62 CApaApplication* RApaApplication::Application() |
101 { |
63 { |
102 return iApplication; |
64 return iApplication; |
103 } |
65 } |
104 |
66 |
105 void CApaExe::CreateApplicationL(TApaApplicationFactory aApplicationFactory) |
67 void RApaApplication::ScheduleForAsyncDeletion(TBool aDoDelete) |
106 { |
68 { |
107 __ASSERT_ALWAYS(!iApplication,Panic(EPanicApplicationAlreadyExists)); |
69 iScheduledForDeletion = aDoDelete; |
108 iApplication = aApplicationFactory.CreateApplicationL(); |
|
109 iFileUid = aApplicationFactory.AppFileUid(); |
|
110 User::LeaveIfNull(iApplication); |
|
111 iAppName = aApplicationFactory.AppFileNameL(); |
|
112 UpdateAppsRefToThis(); |
|
113 } |
70 } |
114 |
71 |
115 #endif // USING_ECOM_RECOGS |
72 TBool RApaApplication::IsScheduleForAsyncDeletion() const |
116 |
|
117 EXPORT_C void CApaDocument::OpenFileL(CFileStore*&, RFile&) |
|
118 { |
73 { |
119 } |
74 return iScheduledForDeletion; |
120 |
|
121 EXPORT_C void CApaDocument::Reserved_2() |
|
122 {} |
|
123 |
|
124 |
|
125 ///////////////////// |
|
126 // CApaApplication |
|
127 ///////////////////// |
|
128 |
|
129 /** Constructor for CApaApplication */ |
|
130 EXPORT_C CApaApplication::CApaApplication() |
|
131 { |
|
132 } |
|
133 |
|
134 EXPORT_C TFileName CApaApplication::AppFullName()const |
|
135 /** Returns the full name and path of the application. |
|
136 |
|
137 The default implementation returns the full path name of the application DLL. |
|
138 |
|
139 An application can provide its own implementation. |
|
140 |
|
141 @return Full path name of the application. |
|
142 @see CApaApplication::DllName() */ |
|
143 { |
|
144 return DllName(); |
|
145 } |
75 } |
146 |
76 |
147 |
77 |
148 EXPORT_C TFileName CApaApplication::DllName()const |
|
149 /** Returns the full name and path of the loaded application DLL. |
|
150 |
|
151 @return Full path name of the application DLL. */ |
|
152 { |
|
153 __ASSERT_DEBUG(iAppHolder, Panic(EDPanicNoAppHolder)); |
|
154 return iAppHolder->FileName(); |
|
155 } |
|
156 |
|
157 |
|
158 EXPORT_C TInt CApaApplication::GenerateFileName(RFs& aFs,TFileName& aRootName) |
|
159 /** Generates a unique filename based on the file name contained within the specified |
|
160 full path name. |
|
161 |
|
162 If necessary, the function creates the directory structure that is defined |
|
163 in the specified full path name. |
|
164 |
|
165 If the file name does not yet exist, then this is the file name chosen. If |
|
166 this file name already exists, then a file name of the form: name(nn) is generated, |
|
167 where nn are decimal digits. The value of nn is incremented until a name is |
|
168 generated that is unique within the directory structure. A minimum of two |
|
169 decimal digits is generated. |
|
170 |
|
171 The function is used by the UI framework. |
|
172 |
|
173 @param aFs Handle to a file server session. |
|
174 @param aRootName The full path name. |
|
175 @return KErrNone if successful, otherwise one of the other system-wide error |
|
176 codes. Specifically: KErrBadName if the file name portion of the specified |
|
177 full path name has invalid format; KErrArgument if the drive, path or file |
|
178 name parts are missing from the specified full path name; KErrOverflow if |
|
179 the generated filename becomes too long; KErrNoMemory if there is insufficient |
|
180 memory to perform the operation. |
|
181 @see CEikAppUi */ |
|
182 { |
|
183 // check that filename is valid |
|
184 if (!aFs.IsValidName(aRootName)) |
|
185 return KErrBadName; |
|
186 // |
|
187 // check that a drive, path and root filename have been specified |
|
188 TParsePtr parsePtr(aRootName); |
|
189 if (!parsePtr.DrivePresent() || !parsePtr.PathPresent() || !parsePtr.NamePresent()) |
|
190 return KErrArgument; |
|
191 // |
|
192 // create the path if necessary |
|
193 TInt ret=aFs.MkDirAll(parsePtr.DriveAndPath()); |
|
194 if (ret!=KErrNone && ret!=KErrAlreadyExists) |
|
195 return ret; |
|
196 // |
|
197 // Create the Rbuf object to hold a filename (return if no mem available) |
|
198 RBuf newName; |
|
199 ret = newName.Create(aRootName, KMaxFileName+8); |
|
200 if (ret!=KErrNone) |
|
201 return KErrNoMemory; |
|
202 // |
|
203 // generate a valid filename that doesn't already exist... |
|
204 TEntry entry; |
|
205 TInt i=1; |
|
206 _LIT(KFormatStringOne,"%S%S(%02d)%S"); |
|
207 TBuf<16> format; |
|
208 format=KFormatStringOne; |
|
209 while (aFs.Entry(newName,entry)==KErrNone) // Continue until DoesNotExist or PathDoesNotExist, etc |
|
210 { |
|
211 if (i>=100) |
|
212 { |
|
213 _LIT(KFormatStringTwo,"%S%S(%d)%S"); |
|
214 format=KFormatStringTwo; |
|
215 } |
|
216 TPtrC driveAndPath=parsePtr.DriveAndPath(); |
|
217 TPtrC name=parsePtr.Name(); |
|
218 TPtrC ext=parsePtr.Ext(); |
|
219 newName.Format(format,&driveAndPath,&name,i++,&ext); |
|
220 if (newName.Length()>KMaxFileName) |
|
221 { |
|
222 newName.Close(); |
|
223 return KErrOverflow; |
|
224 } |
|
225 } |
|
226 // |
|
227 // set the new filename and return |
|
228 aRootName = newName; |
|
229 newName.Close(); |
|
230 return KErrNone; |
|
231 } |
|
232 |
|
233 |
|
234 EXPORT_C CDictionaryStore* CApaApplication::OpenIniFileL(RFs& aFs)const |
|
235 /** Opens the .ini file associated with the application, constructs the dictionary |
|
236 store object and returns a pointer to it. |
|
237 |
|
238 The implementation of this function is provided by the OpenIniFileLC() function. |
|
239 The function pops the pointer returned by OpenIniFileLC() from the cleanup |
|
240 stack. |
|
241 |
|
242 @param aFs Handle to a file server session. |
|
243 @return A pointer to the dictionary store object representing the application's |
|
244 .ini file. |
|
245 @see CApaApplication::OpenIniFileLC() */ |
|
246 { |
|
247 CDictionaryStore* store=OpenIniFileLC(aFs); |
|
248 CleanupStack::Pop(); // store |
|
249 return store; |
|
250 } |
|
251 |
|
252 EXPORT_C CApaApplication::~CApaApplication() |
|
253 { |
|
254 #ifdef USING_ECOM_RECOGS |
|
255 if (iDtorKey!=TUid::Null()) // only some CApaApplication objects are ECom objects (i.e. only those corresponding to embedded applications, not top-level applications) |
|
256 { |
|
257 REComSession::DestroyedImplementation(iDtorKey); |
|
258 } |
|
259 #endif // USING_ECOM_RECOGS |
|
260 iAppHolder = NULL; |
|
261 } |
|
262 |
|
263 EXPORT_C void CApaApplication::NewAppServerL(CApaAppServer*& /*aAppServer*/) |
|
264 /** Virtual function called by the framework when the application |
|
265 has been launched as a server application. |
|
266 Applications that wish to be used as server applications must |
|
267 override this function to return their implemetation of the server. |
|
268 @param aAppServer The server pointer to be set. */ |
|
269 { |
|
270 User::Leave(KErrNotSupported); |
|
271 } |
|
272 |
|
273 /** Reserved for future use */ |
|
274 EXPORT_C void CApaApplication::CApaApplication_Reserved1() |
|
275 { |
|
276 } |
|
277 |
|
278 /** Reserved for future use */ |
|
279 EXPORT_C void CApaApplication::CApaApplication_Reserved2() |
|
280 { |
|
281 } |
|
282 |
|
283 ///////////////////////////// |
|
284 // CApaDocument |
|
285 ///////////////////////////// |
|
286 |
|
287 /** Constructor for CApaDocument */ |
|
288 EXPORT_C CApaDocument::CApaDocument() |
|
289 { |
|
290 } |
|
291 |
|
292 EXPORT_C CApaDocument::CApaDocument(CApaApplication& aApp,CApaProcess& aProcess) |
|
293 : iApplication(&aApp), |
|
294 iApaProcess(&aProcess) |
|
295 /** Constructs the document object with the specified application and process. |
|
296 |
|
297 Derived classes must define and implement a constructor through which both |
|
298 the associated application and process can be specified. A typical implementation |
|
299 calls this constructor through a constructor initialization list. |
|
300 |
|
301 @param aApp The application. |
|
302 @param aProcess The process. |
|
303 @see CEikDocument */ |
|
304 {} |
|
305 |
|
306 |
|
307 EXPORT_C CApaDocument::~CApaDocument() |
|
308 /** Destructor. |
|
309 |
|
310 The implementation is empty. */ |
|
311 { |
|
312 iContainer = NULL; |
|
313 iApplication = NULL; |
|
314 iApaProcess = NULL; |
|
315 } |
|
316 |
|
317 |
|
318 EXPORT_C CApaDocument::TCapability CApaDocument::Capability() const |
|
319 /** Gets the document's capabilities. |
|
320 |
|
321 Capabilities are encapsulated by an instance of a TCapability class, a public |
|
322 class defined inside this class. |
|
323 |
|
324 The default implementation returns a default TCapability object, indicating |
|
325 that the document does not support any of the defined capabilities. |
|
326 |
|
327 If a document does support one or more of the capabilities, it should override |
|
328 this function to return a suitably initialised object. |
|
329 |
|
330 @return The document's capabilities */ |
|
331 { |
|
332 return TCapability(); |
|
333 } |
|
334 |
|
335 |
|
336 EXPORT_C void CApaDocument::ValidatePasswordL() const |
|
337 /** Checks the document password. |
|
338 |
|
339 The default implementation is empty. |
|
340 |
|
341 If a document is intended to be password protected, the UI application should |
|
342 provide an implementation that forces the user to enter the password and validate |
|
343 the input. |
|
344 |
|
345 If the document is protected by a password and the password entered by the |
|
346 user is incorrect, the function should leave with KErrLocked, otherwise it |
|
347 should just return. */ |
|
348 {} |
|
349 |
|
350 |
|
351 EXPORT_C CPicture* CApaDocument::GlassPictureL() |
|
352 // Return handle to glass picture, creating one if not already created. |
|
353 // returns NULL as glass pictures are not supported by default |
|
354 /** Gets an object that can draw a representation of the document's content. |
|
355 |
|
356 If the document supports being embedded as a glass door, then the UI application |
|
357 must provide an implementation for this function. |
|
358 |
|
359 The default implementation raises an APPARC 8 panic. |
|
360 |
|
361 @return A pointer to a glass door. */ |
|
362 { |
|
363 Panic(EPanicNoGlassDoorMethodSupplied); |
|
364 // |
|
365 return NULL; |
|
366 } |
|
367 |
|
368 |
|
369 EXPORT_C void CApaDocument::ExternalizeL(RWriteStream& /*aStream*/)const |
|
370 {} |
|
371 |
|
372 EXPORT_C CApaDocument::TCapability::TCapability() |
|
373 :iCapability(0),TCapability_Reserved1(0) |
|
374 /** Constructs a default capability object. |
|
375 |
|
376 All capabilities are marked as "not supported". */ |
|
377 {} |
|
378 |
|
379 ///////////////////////////// |
|
380 // TApaAppHolderInfo |
|
381 ///////////////////////////// |
|
382 |
|
383 class TApaAppHolderInfo |
|
384 { |
|
385 public: |
|
386 TApaAppHolderInfo(CApaAppHolder* aAppHolder); |
|
387 public: |
|
388 CApaAppHolder* iAppHolder; |
|
389 TBool iToBeRemoved; |
|
390 }; |
|
391 |
|
392 TApaAppHolderInfo::TApaAppHolderInfo(CApaAppHolder* aAppHolder) |
|
393 :iAppHolder(aAppHolder), iToBeRemoved(EFalse) |
|
394 { |
|
395 } |
|
396 |
|
397 ///////////////////////////// |
|
398 // CApaParentProcessMonitor |
|
399 ///////////////////////////// |
|
400 |
|
401 class CApaParentProcessMonitor : public CActive |
|
402 { |
|
403 public: // Construction / destruction |
|
404 static CApaParentProcessMonitor* NewL(TProcessId aProcessId); |
|
405 ~CApaParentProcessMonitor(); |
|
406 void ConstructL(); |
|
407 private: |
|
408 CApaParentProcessMonitor(TProcessId aProcessId); |
|
409 public: // From CActive |
|
410 void RunL(); |
|
411 void DoCancel(); |
|
412 private: |
|
413 TProcessId iProcessId; |
|
414 RProcess iProcess; |
|
415 }; |
|
416 |
|
417 CApaParentProcessMonitor* CApaParentProcessMonitor::NewL(TProcessId aProcessId) |
|
418 { |
|
419 CApaParentProcessMonitor* self=new (ELeave) CApaParentProcessMonitor(aProcessId); |
|
420 CleanupStack::PushL(self); |
|
421 self->ConstructL(); |
|
422 CleanupStack::Pop(self); |
|
423 return self; |
|
424 } |
|
425 |
|
426 CApaParentProcessMonitor::CApaParentProcessMonitor(TProcessId aProcessId) |
|
427 : CActive(EPriorityLow) |
|
428 { |
|
429 iProcessId=aProcessId; |
|
430 } |
|
431 |
|
432 CApaParentProcessMonitor::~CApaParentProcessMonitor() |
|
433 { |
|
434 Cancel(); |
|
435 } |
|
436 |
|
437 void CApaParentProcessMonitor::ConstructL() |
|
438 { |
|
439 User::LeaveIfError(iProcess.Open(iProcessId)); |
|
440 iProcess.Logon(iStatus); |
|
441 if(iStatus==KErrNoMemory) |
|
442 { |
|
443 User::WaitForRequest(iStatus); |
|
444 User::Leave(KErrNoMemory); |
|
445 } |
|
446 CActiveScheduler::Add(this); |
|
447 SetActive(); |
|
448 } |
|
449 |
|
450 void CApaParentProcessMonitor::RunL() |
|
451 { |
|
452 // Do something that will kill the child when the parent process terminates |
|
453 if(iStatus==KErrNone) |
|
454 { |
|
455 RProcess proc; |
|
456 proc.Terminate(KErrNone); |
|
457 } |
|
458 } |
|
459 |
|
460 void CApaParentProcessMonitor::DoCancel() |
|
461 { |
|
462 iProcess.LogonCancel(iStatus); |
|
463 } |
|
464 |
|
465 ///////////////////////////// |
|
466 // CApaProcess |
|
467 ///////////////////////////// |
|
468 |
|
469 /** Constructor for CApaProcess */ |
|
470 EXPORT_C CApaProcess::CApaProcess() |
|
471 { |
|
472 } |
|
473 |
|
474 EXPORT_C CApaProcess* CApaProcess::NewL(const RFs& aFs) |
|
475 /** Creates and returns a pointer to a new application process. |
|
476 |
|
477 This function is not used by UI applications. |
|
478 |
|
479 @param aFs Handle to a file server session. |
|
480 @return Pointer to the new application process. */ |
|
481 { |
|
482 CApaProcess* self=new(ELeave) CApaProcess(aFs); |
|
483 CleanupStack::PushL(self); |
|
484 self->ConstructL(); |
|
485 CleanupStack::Pop(); |
|
486 return self; |
|
487 } |
|
488 |
|
489 EXPORT_C CApaProcess::CApaProcess(const RFs& aFs) |
|
490 :iFsSession(aFs) |
|
491 /** Constructs the application process object with the specified file session handle. |
|
492 |
|
493 Derived classes must define and implement a constructor through which |
|
494 the file session handle can be specified. A |
|
495 typical implementation calls this constructor through a constructor initialization |
|
496 list. |
|
497 |
|
498 This constructor is used by the UI framework. |
|
499 |
|
500 @deprecated |
|
501 @param aFs Handle to a file server session */ |
|
502 {} |
|
503 |
|
504 const TInt KPriorityGreaterThanShutter=102; |
|
505 |
|
506 EXPORT_C void CApaProcess::ConstructL() |
|
507 /** Completes construction of the application process object. |
|
508 |
|
509 Implementers of derived classes must call this function as part of the second |
|
510 stage construction of an object. Typically, derived classes implement their |
|
511 own NewL() function and call ConstructL() as part of that implementation. */ |
|
512 { |
|
513 // |
|
514 iAppList = new(ELeave) CArrayFixFlat<TApaAppHolderInfo>(KAppProcessArrayGranularity); |
|
515 iDocList = new(ELeave) CArrayFixFlat<CApaDocument*>(KAppProcessArrayGranularity); |
|
516 iMainDocFileName = HBufC::NewL(KMaxFileName); |
|
517 iApplicationRemover=CIdle::NewL(KPriorityGreaterThanShutter); // Use an idle object so that app has chance to clear its call stack |
|
518 } |
|
519 |
|
520 EXPORT_C void CApaProcess::ConstructL(TProcessId aParentProcessId) |
|
521 /** Completes construction of the application process object, passing in a Parent Process Identifier. |
|
522 |
|
523 Implementers of derived classes must call this function as part of the second |
|
524 stage construction of an object. Typically, derived classes implement their |
|
525 own NewL() function and call ConstructL() as part of that implementation. |
|
526 |
|
527 @param aParentProcessId Id of the parent process. This process will terminate when the parent does. */ |
|
528 { |
|
529 ConstructL(); |
|
530 if(KNullProcessId!=aParentProcessId) |
|
531 { |
|
532 iMonitor=CApaParentProcessMonitor::NewL(aParentProcessId); |
|
533 } |
|
534 } |
|
535 |
|
536 EXPORT_C CApaProcess::~CApaProcess() |
|
537 // If this is called without calling ResetL() or CApaDocument::SaveL() first, data may be lost |
|
538 // |
|
539 /** Frees resources prior to destruction. |
|
540 |
|
541 Documents must be saved before the application process is deleted, otherwise |
|
542 data may be lost. |
|
543 |
|
544 In debug mode, the destructor raises an APPARC 6 panic if documents still |
|
545 exist, and an APPARC 5 panic if applications still exist. */ |
|
546 { |
|
547 if (iMainDoc) |
|
548 { |
|
549 DestroyDocument(iMainDoc); |
|
550 iMainDoc = NULL; |
|
551 } |
|
552 if (iDocList) |
|
553 { |
|
554 __ASSERT_DEBUG(iDocList->Count()==0,Panic(EPanicDocListNotEmpty)); |
|
555 for (TInt i=iDocList->Count()-1 ; i>=0 ; i--) |
|
556 { |
|
557 delete (*iDocList)[i]; // delete stray doc's in release mode, just to be tidy |
|
558 } |
|
559 } |
|
560 if (iAppList) |
|
561 { |
|
562 for (TInt i=iAppList->Count()-1 ; i>=0 ; i--) |
|
563 { |
|
564 delete ((*iAppList)[i]).iAppHolder; |
|
565 } |
|
566 } |
|
567 delete iAppList; |
|
568 delete iDocList; |
|
569 delete iMainDocFileName; |
|
570 delete iApplicationRemover; |
|
571 delete iMonitor; |
|
572 } |
|
573 |
|
574 |
|
575 EXPORT_C void CApaProcess::ResetL() |
|
576 /** Resets the the application process to its initial state. |
|
577 |
|
578 Specifically, it saves the main document, deletes the main and all embedded |
|
579 documents from memory, resets the main document filename and deletes all applications |
|
580 except the main application. |
|
581 |
|
582 The function can leave if saving the main document fails. */ |
|
583 { |
|
584 if (iMainDoc) |
|
585 { |
|
586 iMainDoc->SaveL(); |
|
587 DeleteAllDocs(); // sets iMainDoc to NULL, deletes all apps except main |
|
588 } |
|
589 __ASSERT_DEBUG(iMainDocFileName, Panic(EPanicNoDocument)); |
|
590 *iMainDocFileName=KNullDesC; |
|
591 } |
|
592 |
|
593 |
|
594 void CApaProcess::DeleteAllDocs() |
|
595 // deletes all docs |
|
596 // deletes all apps except main app |
|
597 // sets iMainDoc* to NULL |
|
598 // |
|
599 { |
|
600 CApaAppHolder* mainAppHolder=NULL; |
|
601 if (iMainDoc) |
|
602 { |
|
603 __ASSERT_DEBUG(iMainDoc->Application(), Panic(EDPanicNoApp)); |
|
604 mainAppHolder = iMainDoc->Application()->iAppHolder; |
|
605 for (TInt i=iDocList->Count()-1 ; i>=0 ; i--) |
|
606 if ((*iDocList)[i]==iMainDoc) |
|
607 { |
|
608 iDocList->Delete(i); // removes from array, but doesnt destroy |
|
609 delete iMainDoc; |
|
610 iMainDoc = NULL; |
|
611 } |
|
612 } |
|
613 __ASSERT_ALWAYS(iDocList->Count()==0,Panic(EPanicDocListNotEmpty)); |
|
614 iDocList->Reset(); |
|
615 if (iAppList) |
|
616 { |
|
617 for (TInt ii=iAppList->Count()-1 ; ii>=0 ; ii--) // need to iterate backwards as the array changes size during the loop |
|
618 { |
|
619 if ((*iAppList)[ii].iAppHolder!=mainAppHolder) |
|
620 { |
|
621 delete (*iAppList)[ii].iAppHolder; |
|
622 iAppList->Delete(ii); |
|
623 } |
|
624 } |
|
625 iAppList->Compress(); |
|
626 } |
|
627 } |
|
628 |
|
629 |
|
630 EXPORT_C void CApaProcess::SetMainDocFileName(const TDesC& aMainDocFileName) |
|
631 /** Sets the filename of the main document. |
|
632 |
|
633 @param aMainDocFileName The filename to be set. |
|
634 @panic APPARC 7 If the length of aMainDocFileName is greater than KMaxFileName or the |
|
635 length of the last filename set by SetMainDocFileNameL if greater |
|
636 @see KMaxFileName */ |
|
637 { |
|
638 __ASSERT_DEBUG( iMainDocFileName, Panic(EPanicNullPointer)); |
|
639 __ASSERT_ALWAYS( aMainDocFileName.Length()<=iMainDocFileName->Des().MaxLength() ,Panic(EPanicFileNameTooLong)); |
|
640 *iMainDocFileName = aMainDocFileName; |
|
641 } |
|
642 |
|
643 EXPORT_C void CApaProcess::SetMainDocFileNameL(const TDesC& aMainDocFileName) |
|
644 /** Sets the filename of the main document. |
|
645 |
|
646 @param aMainDocFileName The filename to be set. There is no restriction on the |
|
647 length of this descriptor. */ |
|
648 { |
|
649 __ASSERT_ALWAYS( iMainDocFileName, Panic(EPanicNullPointer)); |
|
650 const TInt newLength = aMainDocFileName.Length() < KMaxFileName ? KMaxFileName : aMainDocFileName.Length(); |
|
651 if (newLength != iMainDocFileName->Des().MaxLength()) |
|
652 { |
|
653 HBufC* const newMainDocFileName = HBufC::NewL(newLength); |
|
654 delete iMainDocFileName; |
|
655 iMainDocFileName = newMainDocFileName; |
|
656 } |
|
657 SetMainDocFileName(aMainDocFileName); |
|
658 } |
|
659 |
|
660 EXPORT_C void CApaProcess::SetMainDocument(CApaDocument* aDocument) |
|
661 /** Sets the main document. |
|
662 |
|
663 @param aDocument A pointer to the document to be set as the main document |
|
664 of the application process. This must be a an object created by the AddNewDocumentL() |
|
665 or OpenNewDocumentL() functions |
|
666 @see CApaProcess::AddNewDocumentL() |
|
667 @see CApaProcess::OpenNewDocumentL() */ |
|
668 { |
|
669 __ASSERT_ALWAYS( iDocList, Panic(EPanicNullPointer)); |
|
670 // check that the prospective main doc has actually been added to the array |
|
671 for (TInt i=iDocList->Count()-1 ; i>=0 ; i--) |
|
672 { |
|
673 if ((*iDocList)[i]==aDocument) |
|
674 break; |
|
675 if (i==0) |
|
676 Panic(EPanicNoDocument); |
|
677 } |
|
678 // assign it once it has checked out |
|
679 iMainDoc = aDocument; |
|
680 } |
|
681 |
|
682 EXPORT_C CApaDocument* CApaProcess::AddNewDocumentL(TApaApplicationFactory aApplicationFactory) |
|
683 /** Creates and adds a new document using the specified application factory. |
|
684 |
|
685 The document may be a main document or an embedded document. |
|
686 |
|
687 Any document created with this function must be destroyed using DestroyDocument(). |
|
688 |
|
689 @param aApplicationFactory Should be created implicitly by passing a pointer to |
|
690 a factory function, an ECOM plugin UID, or a CImplementationInformation reference. |
|
691 @return A pointer to the new document. |
|
692 @see CApaProcess::DestroyDocument() |
|
693 @see CApaApplication */ |
|
694 { |
|
695 #ifdef USING_ECOM_RECOGS |
|
696 __SHOW_TRACE(_L("Starting CApaProcess::AddNewDocumentL")); |
|
697 __APA_PROFILE_START(0); |
|
698 |
|
699 CApaAppHolder* appHolder = AddAppExeL(aApplicationFactory); |
|
700 |
|
701 // use the app to create a doc |
|
702 CApaDocument* doc=NULL; |
|
703 TRAPD(ret,doc=CreateDocL(appHolder->Application())); |
|
704 if (ret!=KErrNone) |
|
705 // remove app as it has been orphaned |
|
706 RemoveApp(appHolder); |
|
707 User::LeaveIfError(ret); |
|
708 __PROFILE_END(0); |
|
709 return doc; |
|
710 #else // USING_ECOM_RECOGS |
|
711 (void)aApplicationFactory; |
|
712 return NULL; |
|
713 #endif // USING_ECOM_RECOGS |
|
714 } //lint !e1762 Member function could be made const - Not true |
|
715 |
|
716 |
|
717 |
|
718 void CApaProcess::RemoveApp(CApaAppHolder* aAppHolder) |
|
719 // removes app holder from the list if it exists, panics otherwise |
|
720 { |
|
721 __ASSERT_ALWAYS(iAppList, Panic(EPanicNullPointer)); |
|
722 TInt i = 0; |
|
723 for (i=iAppList->Count()-1 ; i>=0 ; i--) |
|
724 { |
|
725 if ((*iAppList)[i].iAppHolder==aAppHolder) // the main app may be alive on its own if Reset() has just been called |
|
726 { |
|
727 delete aAppHolder; // the main app may be alive on its own if Reset() has just been called |
|
728 iAppList->Delete(i); |
|
729 break; |
|
730 } |
|
731 } |
|
732 if (i<0) |
|
733 Panic(EPanicAppNotInList); |
|
734 } |
|
735 |
|
736 |
|
737 EXPORT_C CApaDocument* CApaProcess::OpenNewDocumentL(CFileStore*& aStore,CStreamDictionary*& aStreamDic,const TDesC& aDocFullFileName,TUint aFileMode) |
|
738 /** Opens the specified file and restores the content as a document. |
|
739 |
|
740 The created document can be merged into or embedded in another document. |
|
741 |
|
742 Any document created with this function must be destroyed using DestroyDocument(). |
|
743 |
|
744 @param aStore On return, this contains a pointer to the store object created |
|
745 during the restore. |
|
746 @param aStreamDic On return, this contains a pointer to the stream dictionary |
|
747 object created during the restore. |
|
748 @param aDocFullFileName The name of the file containing the document. |
|
749 @param aFileMode The mode in which to open the file. |
|
750 @return A pointer to the restored document. |
|
751 @see TFileMode |
|
752 @see CApaProcess::DestroyDocument() */ |
|
753 { |
|
754 __SHOW_TRACE(_L("Starting CApaProcess::OpenNewDocumentL")); |
|
755 __APA_PROFILE_START(1); |
|
756 TParse parser; |
|
757 User::LeaveIfError(iFsSession.Parse(aDocFullFileName,parser)); |
|
758 // open doc as a file store & read in the header |
|
759 CFileStore* docStore; |
|
760 CStreamDictionary* streamDic = ReadRootStreamLC(FsSession(),docStore,parser.FullName(),aFileMode); |
|
761 CleanupStack::PushL(docStore); |
|
762 // read in the app id info |
|
763 TApaAppIdentifier appId=ReadAppIdentifierL(*docStore,*streamDic); |
|
764 // create the doc |
|
765 CApaDocument* importedDoc = AddNewDocumentL(appId.iAppUid); |
|
766 // restore the document |
|
767 TApaDocCleanupItem cleanup(this,importedDoc); |
|
768 CleanupStack::PushL(cleanup); |
|
769 importedDoc->RestoreL(*docStore,*streamDic); |
|
770 CleanupStack::Pop(3); //docStore,importedDoc,streamDic |
|
771 aStore = docStore; |
|
772 aStreamDic = streamDic; |
|
773 __PROFILE_END(1); |
|
774 return importedDoc; |
|
775 } |
|
776 |
|
777 EXPORT_C TApaAppIdentifier CApaProcess::ReadAppIdentifierL(const CStreamStore& aStore,const CStreamDictionary& aStreamDic) |
|
778 // this is a static method |
|
779 /** Reads the application identifier from its stream in the specified store and |
|
780 returns it. |
|
781 |
|
782 The location of the stream is found in the specified stream dictionary. |
|
783 |
|
784 @param aStore The store from which the application identifier should be read. |
|
785 @param aStreamDic The stream dictionary containing the stream ID of the application |
|
786 identifier stream. The stream dictionary can be found in the root stream of |
|
787 the store. |
|
788 @return The application identifier. */ |
|
789 { |
|
790 __SHOW_TRACE(_L("Starting CApaProcess::ReadAppIdentifierL")); |
|
791 TStreamId infoStreamId=aStreamDic.At(KUidAppIdentifierStream); |
|
792 TApaAppIdentifier appId; |
|
793 // create a stream and read in the data |
|
794 RStoreReadStream stream; |
|
795 stream.OpenLC(aStore,infoStreamId); |
|
796 stream>> appId; |
|
797 stream.Close(); |
|
798 CleanupStack::PopAndDestroy(); // stream |
|
799 return appId; |
|
800 } |
|
801 |
|
802 |
|
803 EXPORT_C void CApaProcess::WriteAppIdentifierL(CStreamStore& aStore,CStreamDictionary& aStreamDic,const TApaAppIdentifier& aAppId) |
|
804 // this is a static method |
|
805 /** Writes the application identifier to a new stream in the specified store and |
|
806 records the location of this stream in the specified stream dictionary. |
|
807 |
|
808 @param aStore The store to which the application identifier should be written. |
|
809 |
|
810 @param aStreamDic The stream dictionary. |
|
811 @param aAppId The application identifier to be externalised to a stream. */ |
|
812 { |
|
813 __SHOW_TRACE(_L("Starting CApaProcess::WriteAppIdentifierL")); |
|
814 // create a stream |
|
815 RStoreWriteStream stream; |
|
816 TStreamId streamId=stream.CreateLC(aStore); |
|
817 // stream the header |
|
818 stream<< aAppId; |
|
819 stream.CommitL(); |
|
820 CleanupStack::PopAndDestroy(); // id stream |
|
821 // enter the stream in the dictionary |
|
822 aStreamDic.AssignL(KUidAppIdentifierStream,streamId); |
|
823 } |
|
824 |
|
825 |
|
826 EXPORT_C CStreamDictionary* CApaProcess::ReadRootStreamLC(RFs& aFs,CFileStore*& aStore,const TDesC& aDocFullFileName,TUint aFileMode) |
|
827 /** Reads the stream dictionary contained as the root stream in the specified document |
|
828 file. |
|
829 |
|
830 The function constructs, and returns a pointer to the stream dictionary object |
|
831 and puts the pointer to the stream dictionary object onto the cleanup stack. |
|
832 It also returns a pointer to the created file store object through an argument |
|
833 reference. |
|
834 |
|
835 The file must be a valid document file; otherwise the function leaves with one of |
|
836 the system-wide error codes. |
|
837 |
|
838 @param aFs Handle to a file server session. |
|
839 @param aStore On return, a pointer to the newly created file store object. |
|
840 @param aDocFullFileName The full path name of the document file. |
|
841 @param aFileMode The mode in which to open the file. |
|
842 @return A pointer to the stream dictionary object read from the root stream |
|
843 of the store. |
|
844 @see TFileMode */ |
|
845 { // static |
|
846 __SHOW_TRACE(_L("Starting CApaProcess::ReadRootStreamLC (file-name overload)")); |
|
847 CStreamDictionary* const streamDictionary=CStreamDictionary::NewLC(); |
|
848 CFileStore* const store=CFileStore::OpenLC(aFs,aDocFullFileName,aFileMode); |
|
849 DoReadRootStreamL(*streamDictionary, *store); |
|
850 aStore=store; // delay assignment until nothing can go wrong to avoid destroying the store twice if a leave occurs |
|
851 CleanupStack::Pop(store); |
|
852 return streamDictionary; |
|
853 } |
|
854 |
|
855 |
|
856 EXPORT_C CStreamDictionary* CApaProcess::ReadRootStreamLC(CFileStore*& aStore, const RFile& aFile) |
|
857 /** |
|
858 @internalTechnology |
|
859 */ |
|
860 { // static |
|
861 __SHOW_TRACE(_L("Starting CApaProcess::ReadRootStreamLC (file-handle overload)")); |
|
862 CStreamDictionary* const streamDictionary=CStreamDictionary::NewLC(); |
|
863 RFile duplicateFile; |
|
864 CleanupClosePushL(duplicateFile); |
|
865 User::LeaveIfError(duplicateFile.Duplicate(aFile)); // this is because CFileStore::FromLC closes the file its passed (and stores its own duplicate) |
|
866 CFileStore* const store=CFileStore::FromL(duplicateFile); |
|
867 CleanupStack::PopAndDestroy(&duplicateFile); |
|
868 CleanupStack::PushL(store); |
|
869 DoReadRootStreamL(*streamDictionary, *store); |
|
870 aStore=store; // delay assignment until nothing can go wrong to avoid destroying the store twice if a leave occurs |
|
871 CleanupStack::Pop(store); |
|
872 return streamDictionary; |
|
873 } |
|
874 |
|
875 |
|
876 void CApaProcess::DoReadRootStreamL(CStreamDictionary& aStreamDictionary, const CFileStore& aStore) |
|
877 { // static |
|
878 const TStreamId rootStreamId=aStore.Root(); |
|
879 if ((aStore.Type()[1]!=KUidAppDllDoc) || (rootStreamId==KNullStreamId)) |
|
880 { |
|
881 User::Leave(KErrCorrupt); |
|
882 } |
|
883 RStoreReadStream rootStream; |
|
884 rootStream.OpenLC(aStore, rootStreamId); |
|
885 rootStream>>aStreamDictionary; |
|
886 CleanupStack::PopAndDestroy(&rootStream); |
|
887 } |
|
888 |
|
889 |
|
890 EXPORT_C void CApaProcess::WriteRootStreamL(CPersistentStore& aStore,CStreamDictionary& aStreamDic,const CApaApplication& aApp) |
|
891 // this is a static method |
|
892 /** Writes the application identifier (derived from the application object CApaApplication) |
|
893 followed by the stream dictionary to the store and makes the stream dictionary the root stream of the |
|
894 store. |
|
895 |
|
896 Typically, the function is called by the application when it |
|
897 implements a file create or file save type operation. It is called after all |
|
898 model and UI data has been persisted. The IDs of the streams containing the |
|
899 model and UI data should have been lodged in the stream dictionary. |
|
900 |
|
901 In effect, the function finishes off the file save or file |
|
902 create type operation, leaving the file containing the store in a valid state |
|
903 with the standard interface. |
|
904 |
|
905 @param aStore The store to which the root stream is to be written. Before |
|
906 calling this function, a reference to the store must be saved by putting a |
|
907 pointer onto the cleanup stack or by making it member data of a class. This |
|
908 ensures that it is not orphaned in the event of this function leaving. |
|
909 @param aStreamDic The stream dictionary containing the locations and associated |
|
910 UIDs of other streams in the store. |
|
911 @param aApp The application used to create the main document in the file |
|
912 being written. The application identifier to be written is constructed from |
|
913 this application object. */ |
|
914 { |
|
915 __SHOW_TRACE(_L("Starting CApaProcess::WriteRootStreamL(app)")); |
|
916 // get the app dll name |
|
917 TParse dllPath; |
|
918 dllPath.SetNoWild(aApp.DllName(),NULL,NULL); |
|
919 // set up an app identifier |
|
920 TApaAppIdentifier appId(aApp.AppDllUid(),dllPath.NameAndExt()); |
|
921 // Write the root stream |
|
922 WriteRootStreamL(aStore,aStreamDic,appId); |
|
923 } |
|
924 |
|
925 |
|
926 EXPORT_C void CApaProcess::WriteRootStreamL(CPersistentStore& aStore,CStreamDictionary& aStreamDic,const TApaAppIdentifier& aAppId) |
|
927 // this is a static method |
|
928 /** Writes the application identifier followed by the stream dictionary |
|
929 to the store and makes the stream dictionary the root stream of the store. |
|
930 |
|
931 Typically, the function is called by the application when it |
|
932 implements a file create or file save type operation. It is called after all |
|
933 model and UI data has been persisted. The IDs of the streams containing the |
|
934 model and UI data should have been lodged in the stream dictionary. |
|
935 |
|
936 In effect, the function finishes off the file save or file |
|
937 create type operation, leaving the file containing the store in a valid state |
|
938 with the standard interface. |
|
939 |
|
940 @param aStore The store to which the root stream is to be written. Before |
|
941 calling this function, a reference to the store must be saved by putting a |
|
942 pointer onto the cleanup stack or by making it member data of a class. This |
|
943 ensures that it is not orphaned in the event of this function leaving. |
|
944 @param aStreamDic The stream dictionary containing the locations and associated |
|
945 UIDs of other streams in the store. |
|
946 @param aAppId The application identifier to be written into the application |
|
947 identifier stream. */ |
|
948 { |
|
949 __SHOW_TRACE(_L("Starting CApaProcess::WriteRootStreamL(id)")); |
|
950 // create a stream |
|
951 WriteAppIdentifierL(aStore,aStreamDic,aAppId); |
|
952 // externalize the dictionary |
|
953 RStoreWriteStream stream; |
|
954 TStreamId streamId=stream.CreateLC(aStore); |
|
955 stream<< aStreamDic; |
|
956 stream.CommitL(); |
|
957 CleanupStack::PopAndDestroy(); // dictionary stream |
|
958 // set the dictionary stream as the root stream |
|
959 aStore.SetRootL(streamId); |
|
960 } |
|
961 |
|
962 |
|
963 EXPORT_C void CApaProcess::DestroyDocument(CApaDocument* aDoc) |
|
964 /** Destroys the specified document. |
|
965 |
|
966 All references to the document are removed, and associated resources are freed. |
|
967 Specifically, the function deletes any associated application and unloads |
|
968 the application DLL, provided that no other documents of that application |
|
969 type are still open. |
|
970 |
|
971 All document objects created through CApaProcess must be deleted using this |
|
972 function. |
|
973 |
|
974 @param aDoc A pointer to the document to be destroyed. |
|
975 @see CApaApplication |
|
976 @see CApaProcess */ |
|
977 { |
|
978 __SHOW_TRACE(_L("Starting CApaProcess::DestroyDocument(app)")); |
|
979 // |
|
980 if (aDoc) |
|
981 { |
|
982 // delete the doc, keeping a handle to its app |
|
983 CApaApplication* app=aDoc->Application(); |
|
984 __ASSERT_DEBUG(app!=NULL,Panic(EDPanicDocWithNoApp)); |
|
985 // remove the doc from the list, keeping a handle to the doc |
|
986 TBool appStillRequired=EFalse; |
|
987 __ASSERT_ALWAYS(iDocList, Panic(EPanicNullPointer)); |
|
988 for (TInt i=iDocList->Count()-1 ; i>=0 ; i--) |
|
989 {//check through the list, remove the right doc, and see if the app is used by any other docs |
|
990 if ((*iDocList)[i]==aDoc) |
|
991 { |
|
992 iDocList->Delete(i); // removes from array, but doesnt destroy |
|
993 iDocList->Compress(); |
|
994 } |
|
995 else if ((*iDocList)[i]->Application()==app) |
|
996 appStillRequired = ETrue; |
|
997 } |
|
998 // null the main doc handle if we delete the main doc |
|
999 if (aDoc==iMainDoc) |
|
1000 iMainDoc = NULL; |
|
1001 |
|
1002 delete aDoc; // del |
|
1003 |
|
1004 // remove app if no other doc's use it and it's not the main app |
|
1005 if ((!appStillRequired)&&(iMainDoc)&&(app!=iMainDoc->Application())) |
|
1006 { |
|
1007 MarkApplicationForRemoval(app); |
|
1008 __ASSERT_DEBUG(iApplicationRemover, Panic(EDPanicNoAppRemover)); |
|
1009 if (!iApplicationRemover->IsActive()) |
|
1010 { |
|
1011 iApplicationRemover->Start(TCallBack(CApaProcess::IdleRemoveApplications,this)); |
|
1012 } |
|
1013 } |
|
1014 } |
|
1015 } |
|
1016 |
|
1017 |
|
1018 TInt CApaProcess::IdleRemoveApplications(TAny* aThis) |
|
1019 // Remove applications on callback of idle object. Using an idle object gives an embedded application a chance to clear |
|
1020 // its call stack before its dll is closed |
|
1021 // |
|
1022 { |
|
1023 CApaProcess* process=reinterpret_cast<CApaProcess*>(aThis); |
|
1024 __ASSERT_DEBUG(process, Panic(EDPanicNoProcess)); |
|
1025 process->RemoveMarkedApplications(); |
|
1026 return 0; |
|
1027 } |
|
1028 |
|
1029 |
|
1030 void CApaProcess::RemoveMarkedApplications() |
|
1031 // Remove any applications that have been marked for removal, closing their dlls also |
|
1032 // |
|
1033 { |
|
1034 __ASSERT_DEBUG(iAppList, Panic(EPanicNullPointer)); |
|
1035 for (TInt i=iAppList->Count()-1 ; i>=0 ; i--) |
|
1036 if ((*iAppList)[i].iToBeRemoved) |
|
1037 { |
|
1038 delete (*iAppList)[i].iAppHolder; |
|
1039 iAppList->Delete(i); // remove from array |
|
1040 iAppList->Compress(); |
|
1041 } |
|
1042 } |
|
1043 |
|
1044 |
|
1045 void CApaProcess::MarkApplicationForRemoval(const CApaApplication* aApp) |
|
1046 // Mark the application in the app list for removal by idle object |
|
1047 // |
|
1048 { |
|
1049 __ASSERT_DEBUG(aApp!=NULL,Panic(EDPanicRemovingNullApp)); |
|
1050 __ASSERT_DEBUG(iAppList, Panic(EPanicNullPointer)); |
|
1051 // remove the app from the list, keeping a handle to it |
|
1052 for (TInt i=iAppList->Count()-1 ; i>=0 ; i--) |
|
1053 { |
|
1054 __ASSERT_DEBUG((*iAppList)[i].iAppHolder, Panic(EDPanicNoAppHolder)); |
|
1055 if ((*iAppList)[i].iAppHolder->Application()==aApp) |
|
1056 { |
|
1057 (*iAppList)[i].iToBeRemoved=ETrue; |
|
1058 } |
|
1059 } |
|
1060 |
|
1061 } |
|
1062 |
|
1063 |
|
1064 CApaDocument* CApaProcess::CreateDocL(CApaApplication* aApp) |
|
1065 // creates a new doc with aApp and adds it to the list before returning a handle to it |
|
1066 // |
|
1067 { |
|
1068 __SHOW_TRACE(_L("Starting CApaProcess::CreateDocL")); |
|
1069 __ASSERT_DEBUG(aApp,Panic(EDPanicNoApp)); |
|
1070 // |
|
1071 // create a new doc with the app |
|
1072 CApaDocument* doc=aApp->CreateDocumentL(this); //lint !e613 Possible use of null pointer - Asserted above |
|
1073 __ASSERT_ALWAYS(doc!=NULL,Panic(EPanicDocumentNotCreated)); |
|
1074 // add the doc to the list |
|
1075 CleanupStack::PushL(doc); |
|
1076 iDocList->AppendL(doc); |
|
1077 CleanupStack::Pop(); // doc |
|
1078 // return a handle to the doc |
|
1079 return doc; |
|
1080 } |
|
1081 |
|
1082 |
|
1083 CApaAppHolder* CApaProcess::FindAppInListL(const TDesC& aAppFileName,TUid aUid)const |
|
1084 // returns pointer to a matching app, or NULL if not in list |
|
1085 // |
|
1086 { |
|
1087 __ASSERT_DEBUG(iAppList, Panic(EPanicNullPointer)); |
|
1088 TInt index=iAppList->Count(); |
|
1089 if (aUid!=KNullUid) |
|
1090 {// search by UID |
|
1091 while (--index>=0) |
|
1092 { |
|
1093 __ASSERT_DEBUG((*iAppList)[index].iAppHolder, Panic(EDPanicNoAppHolder)); |
|
1094 if ((*iAppList)[index].iAppHolder->Uid()==aUid) |
|
1095 { |
|
1096 (*iAppList)[index].iToBeRemoved = FALSE; |
|
1097 return (*iAppList)[index].iAppHolder; // match found |
|
1098 } |
|
1099 } |
|
1100 } |
|
1101 else |
|
1102 {// search by name as no UID has been supplied |
|
1103 TParse app; TParse suspect; |
|
1104 User::LeaveIfError(app.Set(aAppFileName,NULL,NULL)); |
|
1105 while (--index>=0) |
|
1106 { |
|
1107 __ASSERT_DEBUG((*iAppList)[index].iAppHolder, Panic(EDPanicNoAppHolder)); |
|
1108 suspect.SetNoWild((*iAppList)[index].iAppHolder->FileName(),NULL,NULL); |
|
1109 if (!app.Name().CompareF(suspect.Name())) |
|
1110 { |
|
1111 (*iAppList)[index].iToBeRemoved = FALSE; |
|
1112 return (*iAppList)[index].iAppHolder; // match found |
|
1113 } |
|
1114 } |
|
1115 } |
|
1116 return NULL; // no match found |
|
1117 } |
|
1118 |
|
1119 #ifdef USING_ECOM_RECOGS |
|
1120 CApaExe* CApaProcess::AddAppExeL(TApaApplicationFactory aApplicationFactory) |
|
1121 { |
|
1122 CApaExe* exe = new(ELeave) CApaExe(); |
|
1123 CleanupStack::PushL(exe); |
|
1124 |
|
1125 // create the app |
|
1126 exe->CreateApplicationL(aApplicationFactory); |
|
1127 __ASSERT_DEBUG(exe->Application(), Panic(EPanicNullPointer)); |
|
1128 exe->Application()->PreDocConstructL(); |
|
1129 |
|
1130 // add the application to the list and return a pointer to it |
|
1131 TApaAppHolderInfo info(exe); |
|
1132 __ASSERT_DEBUG(iAppList, Panic(EPanicNullPointer)); |
|
1133 iAppList->AppendL(info); |
|
1134 CleanupStack::Pop(exe); |
|
1135 |
|
1136 return exe; |
|
1137 } |
|
1138 #endif // USING_ECOM_RECOGS |
|
1139 |
|
1140 |
|
1141 EXPORT_C TPtrC CApaProcess::MainDocFileName()const |
|
1142 /** Returns the filename of the main document. |
|
1143 |
|
1144 @return A non-modifiable pointer descriptor to the main document filename. |
|
1145 For non file-based applications, the length of this descriptor is zero. */ |
|
1146 { |
|
1147 if (iMainDocFileName!=NULL) |
|
1148 { |
|
1149 return *iMainDocFileName; |
|
1150 } |
|
1151 return KNullDesC(); |
|
1152 } |
|
1153 |
|
1154 /** Reserved for future use */ |
|
1155 EXPORT_C void CApaProcess::CApaProcess_Reserved1() |
|
1156 { |
|
1157 } |
|
1158 |
|
1159 /** Reserved for future use */ |
|
1160 EXPORT_C void CApaProcess::CApaProcess_Reserved2() |
|
1161 { |
|
1162 } |
|
1163 |
|
1164 ///////////////////////////// |
|
1165 // TApaApplicationFactory |
|
1166 ///////////////////////////// |
|
1167 |
|
1168 /** |
|
1169 Default constructor |
|
1170 */ |
|
1171 |
|
1172 /** Constructor for TApaApplicationFactory */ |
|
1173 EXPORT_C TApaApplicationFactory::TApaApplicationFactory() |
|
1174 :iType(ETypeFunction), |
|
1175 iData(0), |
|
1176 iApplication(NULL) |
|
1177 { |
|
1178 } |
|
1179 |
|
1180 /** |
|
1181 Constructor. |
|
1182 @publishedAll |
|
1183 @released |
|
1184 @param aFunction The function from which the application is to be created. |
|
1185 */ |
|
1186 EXPORT_C TApaApplicationFactory::TApaApplicationFactory(TFunction aFunction) |
|
1187 :iType(ETypeFunction), |
|
1188 iData(reinterpret_cast<TUint>(aFunction)), |
|
1189 iApplication(NULL) |
|
1190 { |
|
1191 } |
|
1192 |
|
1193 /** |
|
1194 Constructor. Use this constructor in preference to the constructor taking a "TUid" parameter |
|
1195 if at all possible as it is much more efficient. |
|
1196 @publishedAll |
|
1197 @released |
|
1198 @param aEmbeddedApplicationInformation The ECOM implementation-information of the embedded application to be created. |
|
1199 */ |
|
1200 EXPORT_C TApaApplicationFactory::TApaApplicationFactory(const CImplementationInformation& aEmbeddedApplicationInformation) |
|
1201 :iType(ETypeEmbeddedApplicationInformation), |
|
1202 iData(reinterpret_cast<TUint>(&aEmbeddedApplicationInformation)), |
|
1203 iApplication(NULL) |
|
1204 { |
|
1205 } |
|
1206 |
|
1207 /** |
|
1208 Constructor. Use the constructor taking a "const CImplementationInformation&" parameter in preference |
|
1209 to this constructor if at all possible as it is much more efficient. |
|
1210 @publishedAll |
|
1211 @released |
|
1212 @param aEmbeddedApplicationUid The ECOM implementation-UID of the embedded application to be created. |
|
1213 */ |
|
1214 EXPORT_C TApaApplicationFactory::TApaApplicationFactory(TUid aEmbeddedApplicationUid) |
|
1215 :iType(ETypeEmbeddedApplicationUid), |
|
1216 iData(aEmbeddedApplicationUid.iUid), |
|
1217 iApplication(NULL) |
|
1218 { |
|
1219 } |
|
1220 |
|
1221 #ifdef USING_ECOM_RECOGS |
|
1222 CApaApplication* TApaApplicationFactory::CreateApplicationL() const |
|
1223 { |
|
1224 CApaApplication* application = NULL; |
|
1225 |
|
1226 switch (iType) |
|
1227 { |
|
1228 case ETypeFunction: |
|
1229 { |
|
1230 __ASSERT_DEBUG(iData, Panic(EPanicNullPointer)); |
|
1231 application=(*reinterpret_cast<TFunction>(iData))(); |
|
1232 break; |
|
1233 } |
|
1234 case ETypeEmbeddedApplicationInformation: |
|
1235 { |
|
1236 __ASSERT_DEBUG(iData, Panic(EPanicNullPointer)); |
|
1237 const CImplementationInformation& embeddedApplicationInformation=*reinterpret_cast<const CImplementationInformation*>(iData); |
|
1238 TUid uid = embeddedApplicationInformation.ImplementationUid(); |
|
1239 application=CreateEmbeddedApplicationL(uid); |
|
1240 break; |
|
1241 } |
|
1242 case ETypeEmbeddedApplicationUid: |
|
1243 { |
|
1244 TUid uid = TUid::Uid(iData); |
|
1245 application=CreateEmbeddedApplicationL(uid); |
|
1246 break; |
|
1247 } |
|
1248 default: |
|
1249 Panic(EPanicBadApplicationFactoryType); |
|
1250 } |
|
1251 |
|
1252 return application; |
|
1253 } |
|
1254 |
|
1255 HBufC* TApaApplicationFactory::AppFileNameL() const |
|
1256 { |
|
1257 HBufC* appFileName = NULL; |
|
1258 switch (iType) |
|
1259 { |
|
1260 case ETypeFunction: |
|
1261 { |
|
1262 // Assume that if the type is a function pointer then the app is not embedded (so |
|
1263 // the filename is the filename of this process). |
|
1264 appFileName = RProcess().FileName().AllocL(); |
|
1265 break; |
|
1266 } |
|
1267 case ETypeEmbeddedApplicationInformation: |
|
1268 { |
|
1269 const CImplementationInformation& embeddedApplicationInformation=*REINTERPRET_CAST(const CImplementationInformation*,iData); |
|
1270 appFileName = FullAppFileNameL(embeddedApplicationInformation.DisplayName()); |
|
1271 break; |
|
1272 } |
|
1273 case ETypeEmbeddedApplicationUid: |
|
1274 { |
|
1275 TUid uid = TUid::Uid(iData); |
|
1276 HBufC* displayName = EmbeddedApplicationDisplayNameLC(uid); |
|
1277 appFileName = FullAppFileNameL(*displayName); |
|
1278 CleanupStack::PopAndDestroy(displayName); |
|
1279 break; |
|
1280 } |
|
1281 default: |
|
1282 Panic(EPanicBadApplicationFactoryType); |
|
1283 } |
|
1284 |
|
1285 return appFileName; |
|
1286 } |
|
1287 |
|
1288 TUid TApaApplicationFactory::AppFileUid() const |
|
1289 { |
|
1290 TUid uid=KNullUid; |
|
1291 switch (iType) |
|
1292 { |
|
1293 case ETypeFunction: |
|
1294 { |
|
1295 uid = RProcess().Type()[2]; |
|
1296 break; |
|
1297 } |
|
1298 case ETypeEmbeddedApplicationInformation: |
|
1299 { |
|
1300 const CImplementationInformation& embeddedApplicationInformation=*REINTERPRET_CAST(const CImplementationInformation*,iData); |
|
1301 uid = embeddedApplicationInformation.ImplementationUid(); |
|
1302 break; |
|
1303 } |
|
1304 case ETypeEmbeddedApplicationUid: |
|
1305 { |
|
1306 uid = TUid::Uid(iData); |
|
1307 break; |
|
1308 } |
|
1309 default: |
|
1310 Panic(EPanicBadApplicationFactoryType); |
|
1311 } |
|
1312 return uid; |
|
1313 } |
|
1314 |
|
1315 HBufC* TApaApplicationFactory::FullAppFileNameL(const TDesC& aAppName) |
|
1316 { |
|
1317 // This was appropriately changed for data caging (binaries placed in \sys\bin\) |
|
1318 TFileName fileName; |
|
1319 Dll::FileName(fileName); |
|
1320 |
|
1321 TParse parse; |
|
1322 parse.SetNoWild(aAppName, &KApplicationLocation, &fileName); |
|
1323 return parse.FullName().AllocL(); |
|
1324 } |
|
1325 |
|
1326 CApaApplication* TApaApplicationFactory::CreateEmbeddedApplicationL(TUid aUid) |
|
1327 { // static |
|
1328 CApaApplication* const application=static_cast<CApaApplication*>(REComSession::CreateImplementationL(aUid,_FOFF(CApaApplication,iDtorKey))); |
|
1329 const TUid appUid = application->AppDllUid(); |
|
1330 __ASSERT_ALWAYS(appUid==aUid, Panic(EPanicUidsDoNotMatch)); |
|
1331 return application; |
|
1332 } |
|
1333 |
|
1334 |
|
1335 HBufC* TApaApplicationFactory::EmbeddedApplicationDisplayNameLC(TUid aUid) |
|
1336 { // static |
|
1337 HBufC* displayName=NULL; |
|
1338 |
|
1339 RImplInfoPtrArray implementationArray; |
|
1340 CleanupStack::PushL(TCleanupItem(CleanupImplementationArray,&implementationArray)); |
|
1341 REComSession::ListImplementationsL(KUidFileEmbeddedApplicationInterfaceUid,implementationArray); |
|
1342 for (TInt i=implementationArray.Count()-1; i>=0; --i) |
|
1343 { |
|
1344 const CImplementationInformation& implementationInformation=*implementationArray[i]; |
|
1345 if (implementationInformation.ImplementationUid().iUid==aUid.iUid) |
|
1346 { |
|
1347 displayName=implementationInformation.DisplayName().AllocL(); |
|
1348 break; |
|
1349 } |
|
1350 } |
|
1351 CleanupStack::PopAndDestroy(&implementationArray); |
|
1352 if (displayName==NULL) |
|
1353 { |
|
1354 User::Leave(KErrNotFound); |
|
1355 } |
|
1356 CleanupStack::PushL(displayName); |
|
1357 |
|
1358 return displayName; |
|
1359 } |
|
1360 |
|
1361 void TApaApplicationFactory::CleanupImplementationArray(TAny* aImplementationArray) |
|
1362 { // static |
|
1363 __ASSERT_DEBUG(aImplementationArray, Panic(EPanicNullPointer)); |
|
1364 RImplInfoPtrArray& implementationArray=*static_cast<RImplInfoPtrArray*>(aImplementationArray); |
|
1365 implementationArray.ResetAndDestroy(); |
|
1366 implementationArray.Close(); |
|
1367 } |
|
1368 |
|
1369 // |
|
1370 // MApaEmbeddedDocObserver |
|
1371 // |
|
1372 |
|
1373 /** Constructor for MApaEmbeddedDocObserver */ |
|
1374 EXPORT_C MApaEmbeddedDocObserver::MApaEmbeddedDocObserver() |
|
1375 { |
|
1376 } |
|
1377 |
|
1378 /** Reserved for future use */ |
|
1379 EXPORT_C void MApaEmbeddedDocObserver::MApaEmbeddedDocObserver_Reserved1() |
|
1380 { |
|
1381 } |
|
1382 |
|
1383 /** Reserved for future use */ |
|
1384 EXPORT_C void MApaEmbeddedDocObserver::MApaEmbeddedDocObserver_Reserved2() |
|
1385 { |
|
1386 } |
|
1387 #endif // USING_ECOM_RECOGS |
|