|
1 // Copyright (c) 1998-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 the License "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 // e32utils\setcap\main.cpp |
|
15 // SETCAP.EXE |
|
16 // Makes a copy of an executable file and gives it the specified capabilities. |
|
17 // It may also, optionally, modify the Secure or Vendor IDs. |
|
18 // This runs under the Symbian OS - it is not a native PC utility. |
|
19 // Command line syntax: |
|
20 // SETCAP source_exe capability [-SID secureId] [-VID vendorId] [destination_path] |
|
21 // source_exe Name and path of an executable file (default path is Z:\SYS\BIN\) |
|
22 // capability Hexadecimal value for capabilities |
|
23 // secureId Optional hexadecimal value of secure ID |
|
24 // vendorId Optional hexadecimal value of vendor ID |
|
25 // destination_path Optional name and path to copy the exe to |
|
26 // (defaults to C:\SYS\BIN\source_exe_name) |
|
27 // Notes |
|
28 // 1. The 'capability' command line argument is the hexadecimal value of the |
|
29 // capabilities when they are represented as a bit-field. E.g. the 3 capabilities |
|
30 // LocalServices, ReadUserData and WriteUserData would together have a value of: |
|
31 // (1<<ECapabilityLocalServices) | (<<ECapabilityReadUserData) | (1<<ECapabilityWriteUserData) |
|
32 // Which in hexadecimal is '1c000' |
|
33 // If the value supplied includes capabilities which aren't supported by the current |
|
34 // OS version, then these are ignored and not added to the file. |
|
35 // 2. If the source executable is in ROM it must be a RAM executable image, not an |
|
36 // execute-in-place image. I.e. its entry in an OBY file must start with "data=" and |
|
37 // not "file=". |
|
38 // For OBY files generated automatically by "ABLD ROMFILE" this needs to be achieved by |
|
39 // using lines similar to the following in the executables MMP file: |
|
40 // ROMTARGET // Empty ROM path means don't include normal execute-in-place file |
|
41 // RAMTARGET \sys\bin\ // Target path (in ROM) for RAM executable image |
|
42 // 3. The Symbian OS only allows one binary file with a given name; the name doesn't |
|
43 // include file path or extension. This means if SETCAP is used to make a copy of a |
|
44 // binary which is already loaded then the copy will not get loaded when used with |
|
45 // RProcess::Create(), instead the already loaded version will be used. To avoid this, |
|
46 // use SETCAP to give the copy a different name. E.g. "SETCAP test.exe 1234 test2.exe" |
|
47 // |
|
48 // |
|
49 |
|
50 /** |
|
51 @file |
|
52 */ |
|
53 |
|
54 #include "setcap.h" |
|
55 |
|
56 #include <f32file.h> |
|
57 |
|
58 TParse SourceName; |
|
59 TParse DestinationName; |
|
60 RFs Fs; |
|
61 |
|
62 #ifdef __WINS__ |
|
63 |
|
64 TInt DoIt() |
|
65 { |
|
66 TInt r; |
|
67 |
|
68 TBuf<MAX_PATH> sName; |
|
69 r = MapEmulatedFileName(sName, SourceName.NameAndExt()); |
|
70 if(r!=KErrNone) |
|
71 return r; |
|
72 |
|
73 TBuf<MAX_PATH> dName; |
|
74 r = MapEmulatedFileName(dName, DestinationName.FullName()); |
|
75 if(r!=KErrNone) |
|
76 return r; |
|
77 |
|
78 if(!Emulator::CopyFile((LPCTSTR)sName.PtrZ(),(LPCTSTR)dName.PtrZ(),FALSE)) |
|
79 return KErrGeneral; |
|
80 |
|
81 HANDLE hFile=Emulator::CreateFile((LPCTSTR)dName.PtrZ(),GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL); |
|
82 if (hFile==INVALID_HANDLE_VALUE) |
|
83 return KErrArgument; |
|
84 |
|
85 return SetCap(hFile); |
|
86 } |
|
87 |
|
88 #else // Not WINS |
|
89 |
|
90 #include <f32file.h> |
|
91 |
|
92 RFile Source; |
|
93 RFile Destination; |
|
94 |
|
95 TInt DoIt() |
|
96 { |
|
97 TInt r; |
|
98 |
|
99 r=Source.Open(Fs,SourceName.FullName(),EFileRead); |
|
100 if(r!=KErrNone) |
|
101 return r; |
|
102 |
|
103 r = Destination.Replace(Fs,DestinationName.FullName(),EFileWrite); |
|
104 if(r!=KErrNone) |
|
105 return r; |
|
106 |
|
107 TUint8* buffer; |
|
108 const TInt KBufferSize = 0x10000; |
|
109 |
|
110 buffer = (TUint8*)User::Alloc(KBufferSize); |
|
111 if(!buffer) |
|
112 return KErrNoMemory; |
|
113 |
|
114 TPtr8 p(buffer,KBufferSize,KBufferSize); |
|
115 TInt n = 0; |
|
116 while (r==KErrNone) |
|
117 { |
|
118 r = Source.Read(p); |
|
119 if(r!=KErrNone || p.Size()==0) |
|
120 break; |
|
121 if (n==0) |
|
122 { |
|
123 // first block contains header |
|
124 if ((TUint)p.Size() < sizeof(E32ImageHeader)) |
|
125 { |
|
126 r = KErrCorrupt; |
|
127 break; |
|
128 } |
|
129 E32ImageHeader* h = (E32ImageHeader*)buffer; |
|
130 r = SetCap(h); |
|
131 } |
|
132 if (r==KErrNone) |
|
133 r = Destination.Write(p); |
|
134 ++n; |
|
135 } |
|
136 |
|
137 delete buffer; |
|
138 |
|
139 Source.Close(); |
|
140 Destination.Close(); |
|
141 |
|
142 return r; |
|
143 } |
|
144 |
|
145 #endif |
|
146 |
|
147 _LIT(KDefaultSourcePath,"z:\\sys\\bin\\"); |
|
148 _LIT(KDefaultDestinationPath,"?:\\sys\\bin\\"); |
|
149 _LIT(KSIDOption,"-SID"); |
|
150 _LIT(KVIDOption,"-VID"); |
|
151 |
|
152 TInt ParseCommandLine() |
|
153 { |
|
154 TBuf<256> c; |
|
155 User::CommandLine(c); |
|
156 |
|
157 // Get exe name |
|
158 TLex l(c); |
|
159 if(SourceName.SetNoWild(l.NextToken(),0,&KDefaultSourcePath)!=KErrNone) |
|
160 return KErrArgument; |
|
161 |
|
162 // Get capability |
|
163 TLex cl(l.NextToken()); |
|
164 if(cl.Val((TInt64&)Capability,EHex)!=KErrNone) |
|
165 return KErrArgument; |
|
166 |
|
167 // Mask out unsupported capabilities |
|
168 TCapabilitySet all; |
|
169 all.SetAllSupported(); |
|
170 ((TCapabilitySet&)Capability).Intersection(all); |
|
171 |
|
172 // We always update capabilities in the headers |
|
173 CapabilitySet = ETrue; |
|
174 |
|
175 // Get options |
|
176 SecureIdSet = EFalse; |
|
177 VendorIdSet = EFalse; |
|
178 TPtrC nextToken; |
|
179 for (;;) |
|
180 { |
|
181 nextToken.Set(l.NextToken()); |
|
182 if (nextToken == KSIDOption) |
|
183 { |
|
184 // SID specified |
|
185 nextToken.Set(l.NextToken()); |
|
186 if (nextToken == KNullDesC) |
|
187 return KErrArgument; |
|
188 TLex sl(nextToken); |
|
189 if(sl.Val(SecureId.iId,EHex)!=KErrNone) |
|
190 return KErrArgument; |
|
191 SecureIdSet = ETrue; |
|
192 } |
|
193 else if (nextToken == KVIDOption) |
|
194 { |
|
195 // VID specified |
|
196 nextToken.Set(l.NextToken()); |
|
197 if (nextToken == KNullDesC) |
|
198 return KErrArgument; |
|
199 TLex sl(nextToken); |
|
200 if(sl.Val(VendorId.iId,EHex)!=KErrNone) |
|
201 return KErrArgument; |
|
202 VendorIdSet = ETrue; |
|
203 } |
|
204 else |
|
205 break; |
|
206 } |
|
207 |
|
208 // Get target path |
|
209 TPtrC s(SourceName.NameAndExt()); |
|
210 TBuf<sizeof(KDefaultDestinationPath)> defaultDestinationPath(KDefaultDestinationPath); |
|
211 defaultDestinationPath[0] = (TUint8) RFs::GetSystemDriveChar(); |
|
212 |
|
213 if(DestinationName.SetNoWild(nextToken,&s,&defaultDestinationPath)!=KErrNone) |
|
214 return KErrArgument; |
|
215 |
|
216 // Check we used all the arguments |
|
217 if (l.NextToken() != KNullDesC) |
|
218 return KErrArgument; |
|
219 |
|
220 return KErrNone; |
|
221 } |
|
222 |
|
223 |
|
224 TInt E32Main() |
|
225 { |
|
226 TInt r; |
|
227 |
|
228 // Turn off lazy dll unloading |
|
229 RLoader l; |
|
230 if ((r=l.Connect())!=KErrNone) |
|
231 return r; |
|
232 r = l.CancelLazyDllUnload(); |
|
233 l.Close(); |
|
234 if (r!=KErrNone) |
|
235 return r; |
|
236 |
|
237 r = ParseCommandLine(); |
|
238 if(r!=KErrNone) |
|
239 return r; |
|
240 r = Fs.Connect(); |
|
241 if(r!=KErrNone) |
|
242 return r; |
|
243 r = Fs.MkDirAll(DestinationName.FullName()); |
|
244 if(r==KErrNone || r==KErrAlreadyExists) |
|
245 r = DoIt(); |
|
246 Fs.Close(); |
|
247 return r; |
|
248 } |