|
1 /* |
|
2 * Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: Implementation of the CVCommandRunnable class |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 #include <vcommandapi.h> |
|
21 #include "rubydebug.h" |
|
22 |
|
23 #include <apaid.h> |
|
24 #include <apgcli.h> |
|
25 #include <apacmdln.h> |
|
26 |
|
27 /** |
|
28 * The version of the streamed data protocol |
|
29 * It is rather likely, that the format of the data streamed changes in the future. |
|
30 * Using the protocol version, the code can check if it knows how to parse the |
|
31 * input stream |
|
32 */ |
|
33 const TInt32 KVCRunnableProtocolVersion = 2; |
|
34 |
|
35 /** |
|
36 * @leave KErrOverflow if aArguments is longer, than KMaxVCArgumentLength |
|
37 * @leave KErrArgument if aAppUid is KNullUidValue |
|
38 */ |
|
39 EXPORT_C CVCRunnable* CVCRunnable::NewL( TUid aAppUid, const TDesC8& aArguments ) |
|
40 { |
|
41 CVCRunnable* self = new ( ELeave ) CVCRunnable; |
|
42 CleanupStack::PushL( self ); |
|
43 self->ConstructL( aAppUid, aArguments ); |
|
44 CleanupStack::Pop( self ); |
|
45 return self; |
|
46 } |
|
47 |
|
48 /** |
|
49 * Factory function |
|
50 * @param aExeName Exe-file to start. Can be full or partical name according to |
|
51 * the RProcess::Create rules. Cannot be KNullDesC |
|
52 * @param aArguments Command line to pass to the application. This object makes |
|
53 * a copy of the passed string |
|
54 * @leave KErrOverflow if aArguments is longer, than KMaxVCArgumentLength or |
|
55 * aExeName is longer, than KMaxOsName |
|
56 * @leave KErrUndeflow if aExeName is empty |
|
57 */ |
|
58 EXPORT_C CVCRunnable* CVCRunnable::NewL( const TDesC& aExeName, const TDesC8& aArguments ) |
|
59 { |
|
60 CVCRunnable* self = new( ELeave ) CVCRunnable; |
|
61 CleanupStack::PushL( self ); |
|
62 self->ConstructL( aExeName, aArguments); |
|
63 CleanupStack::Pop( self ); |
|
64 return self; |
|
65 } |
|
66 |
|
67 /** |
|
68 * Copy the existing CVRunnable |
|
69 */ |
|
70 EXPORT_C CVCRunnable* CVCRunnable::NewL( const CVCRunnable& aOriginal ) |
|
71 { |
|
72 CVCRunnable* self = new (ELeave) CVCRunnable; |
|
73 CleanupStack::PushL( self ); |
|
74 if( aOriginal.Uid() == KNullUid ) |
|
75 { |
|
76 self->ConstructL( aOriginal.ExeName(), aOriginal.Arguments() ); |
|
77 } |
|
78 else |
|
79 { |
|
80 self->ConstructL( aOriginal.Uid(), aOriginal.Arguments() ); |
|
81 } |
|
82 CleanupStack::Pop( self ); |
|
83 return self; |
|
84 } |
|
85 |
|
86 /** |
|
87 * Internalizes from stream |
|
88 * values are read in the same order as ExternalizeL wrote them |
|
89 */ |
|
90 EXPORT_C CVCRunnable* CVCRunnable::NewL( RReadStream &aStream ) |
|
91 { |
|
92 CVCRunnable* self = new (ELeave) CVCRunnable; |
|
93 CleanupStack::PushL( self ); |
|
94 self->ConstructL( aStream ); |
|
95 CleanupStack::Pop( self ); |
|
96 return self; |
|
97 } |
|
98 |
|
99 void CVCRunnable::ConstructL( RReadStream &aStream ) |
|
100 { |
|
101 TInt32 ver; |
|
102 aStream >> ver; |
|
103 __ASSERT_ALWAYS( ver == KVCRunnableProtocolVersion, User::Leave( KErrNotSupported ) ); |
|
104 iExeUid = TUid::Uid( aStream.ReadInt32L() ); |
|
105 iArguments = HBufC8::NewL( aStream.ReadInt32L() ); |
|
106 TPtr8 pArguments = iArguments->Des(); |
|
107 aStream >> pArguments; |
|
108 TInt exeNameLength = aStream.ReadInt32L(); |
|
109 if( exeNameLength > 0 ) |
|
110 { |
|
111 iExeName = HBufC::NewL( exeNameLength ); |
|
112 TPtr pExeName = iExeName->Des(); |
|
113 aStream >> pExeName; |
|
114 } |
|
115 } |
|
116 |
|
117 void CVCRunnable::ConstructL( TUid aAppUid, const TDesC8& aArguments ) |
|
118 { |
|
119 __ASSERT_ALWAYS( aArguments.Length() <= KMaxVCArgumentLength, User::Leave( KErrOverflow) ); |
|
120 __ASSERT_ALWAYS( aAppUid != KNullUid, User::Leave( KErrArgument ) ); |
|
121 iExeUid = TUid::Uid( aAppUid.iUid ); |
|
122 iArguments = HBufC8::NewL( aArguments.Length() ); |
|
123 *iArguments = aArguments; |
|
124 } |
|
125 |
|
126 void CVCRunnable::ConstructL( const TDesC& aExeName, const TDesC8& aArguments ) |
|
127 { |
|
128 __ASSERT_ALWAYS( aArguments.Length() <= KMaxVCArgumentLength, User::Leave( KErrOverflow) ); |
|
129 __ASSERT_ALWAYS( aExeName.Length() <= KMaxFileName, User::Leave( KErrOverflow ) ); |
|
130 __ASSERT_ALWAYS( aExeName.Length() > 0, User::Leave( KErrUnderflow ) ); |
|
131 iExeName = HBufC::NewL( aExeName.Length() ); |
|
132 *iExeName = aExeName; |
|
133 iArguments = HBufC8::NewL( aArguments.Length() ); |
|
134 *iArguments = aArguments; |
|
135 } |
|
136 |
|
137 EXPORT_C CVCRunnable::~CVCRunnable() |
|
138 { |
|
139 delete iExeName; |
|
140 delete iArguments; |
|
141 } |
|
142 |
|
143 /** |
|
144 * Saves the object to stream. |
|
145 * The current format is as follows: |
|
146 * <protocol version: int32><uid: int32; KNullUidValue if no><argument length: int32> |
|
147 * <argument descriptor streamed by the default descriptor ExternalizeL> |
|
148 * <exe filename length><exe filename descriptor only if filename length is not 0> |
|
149 */ |
|
150 EXPORT_C void CVCRunnable::ExternalizeL( RWriteStream &aStream ) const |
|
151 { |
|
152 aStream << KVCRunnableProtocolVersion; |
|
153 aStream << iExeUid.iUid; |
|
154 aStream << static_cast<TInt32>( iArguments->Length() ); |
|
155 aStream << *iArguments; |
|
156 if( iExeName ) |
|
157 { |
|
158 aStream << static_cast<TInt32>( iExeName->Length() ); |
|
159 aStream << *iExeName; |
|
160 } |
|
161 else |
|
162 { |
|
163 aStream << static_cast<TInt32>( 0 ); |
|
164 } |
|
165 } |
|
166 |
|
167 EXPORT_C TBool CVCRunnable::operator==( const CVCRunnable& aRunnable ) const |
|
168 { |
|
169 return ( |
|
170 ( Uid() == aRunnable.Uid()) && |
|
171 ( Arguments() == aRunnable.Arguments() ) && |
|
172 ( ExeName() == aRunnable.ExeName() ) |
|
173 ); |
|
174 } |
|
175 |
|
176 |
|
177 /** |
|
178 * @return The uid of the application to be started |
|
179 */ |
|
180 EXPORT_C const TUid CVCRunnable::Uid() const |
|
181 { |
|
182 return iExeUid; |
|
183 } |
|
184 |
|
185 /** |
|
186 * @return The filename of the application to be started. KNullDesC if there is none |
|
187 */ |
|
188 EXPORT_C const TDesC& CVCRunnable::ExeName() const |
|
189 { |
|
190 if( iExeName ) |
|
191 { |
|
192 return *iExeName; |
|
193 } |
|
194 else |
|
195 { |
|
196 return KNullDesC; |
|
197 } |
|
198 } |
|
199 |
|
200 /** |
|
201 * The arguments to be passed to the application |
|
202 */ |
|
203 EXPORT_C const TDesC8& CVCRunnable::Arguments() const |
|
204 { |
|
205 return *iArguments; |
|
206 } |
|
207 |
|
208 /** |
|
209 * Run the command. In case of aAppUid specified during the construction |
|
210 * application is started via the RApaLsSession::StartApp, otherwise |
|
211 * via the RProcess::Create |
|
212 * @leave System-wide error code. In particular KErrNotFound if there is |
|
213 * no such app in the system |
|
214 */ |
|
215 EXPORT_C void CVCRunnable::ExecuteL() const |
|
216 { |
|
217 RUBY_DEBUG_BLOCK( "CVCRunnable::ExecuteL" ); |
|
218 if( iExeName ) |
|
219 { |
|
220 RProcess process; |
|
221 CleanupClosePushL( process ); |
|
222 // Convert arguments into system_number_of_bits-bit descriptor |
|
223 // (needed for exe, not needed for GUI apps) |
|
224 HBufC* arguments = HBufC::NewLC( iArguments->Length() ); |
|
225 arguments->Des().Copy( *iArguments ); |
|
226 |
|
227 User::LeaveIfError( process.Create( *iExeName, *arguments) ); |
|
228 process.Resume(); |
|
229 |
|
230 CleanupStack::PopAndDestroy( arguments ); |
|
231 CleanupStack::PopAndDestroy( &process ); |
|
232 } |
|
233 else |
|
234 { |
|
235 TApaAppInfo appInfo; |
|
236 RApaLsSession apaLsSession; |
|
237 CleanupClosePushL( apaLsSession ); |
|
238 User::LeaveIfError( apaLsSession.Connect() ); |
|
239 User::LeaveIfError( apaLsSession.GetAppInfo( appInfo, iExeUid ) ); |
|
240 |
|
241 CApaCommandLine* apaCommandLine = CApaCommandLine::NewLC(); |
|
242 apaCommandLine->SetExecutableNameL( appInfo.iFullName ); |
|
243 apaCommandLine->SetTailEndL( *iArguments ); |
|
244 User::LeaveIfError( apaLsSession.StartApp( *apaCommandLine ) ); |
|
245 |
|
246 CleanupStack::PopAndDestroy( apaCommandLine ); |
|
247 CleanupStack::PopAndDestroy( &apaLsSession ); |
|
248 } |
|
249 } |
|
250 |
|
251 //End of file |