|
1 // KernLbxModel.cpp |
|
2 // |
|
3 // Copyright (c) 2010 Accenture. All rights reserved. |
|
4 // This component and the accompanying materials are made available |
|
5 // under the terms of the "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 // Accenture - Initial contribution |
|
11 // |
|
12 #include "KernLbxModel.h" |
|
13 #include "Utils.h" |
|
14 #include <fshell/memoryaccess.h> |
|
15 #include "QResources3.hrh" |
|
16 #include <HAL.h> |
|
17 #include <fshell/common.mmh> |
|
18 #include <fshell/clogger.h> |
|
19 |
|
20 #ifdef FSHELL_APPARC_SUPPORT |
|
21 #include <apgcli.h> |
|
22 #include <APGWGNAM.H> |
|
23 #include <APMREC.H> |
|
24 #endif |
|
25 #ifdef FSHELL_WSERV_SUPPPORT |
|
26 #include <W32STD.H> |
|
27 #endif |
|
28 |
|
29 #include <fshell/ltkutils.h> |
|
30 #include "sandbox.h" |
|
31 |
|
32 using namespace LtkUtils; |
|
33 |
|
34 CKernListBoxData::CKernListBoxData(CKernListBoxModel* aModel) |
|
35 : /*CQikListBoxData(),*/ iModel(aModel) |
|
36 { |
|
37 } |
|
38 |
|
39 CKernListBoxData::~CKernListBoxData() |
|
40 { |
|
41 if (iDelegate) |
|
42 { |
|
43 iDelegate->DataObjectAboutToDestruct(this); |
|
44 } |
|
45 delete iInfo; |
|
46 } |
|
47 |
|
48 |
|
49 CKernListBoxModel::CKernListBoxModel(RMemoryAccess& aMemoryAccess) |
|
50 : iSort(NULL), iMemAccess(aMemoryAccess) |
|
51 { |
|
52 } |
|
53 |
|
54 void CKernListBoxModel::ConstructL() |
|
55 { |
|
56 iUnd = new(ELeave) CUndertaker(*this); |
|
57 iUnd->Register(); |
|
58 #ifdef FSHELL_WSERV_SUPPORT |
|
59 iWsSession = new (ELeave) RWsSession; |
|
60 TInt err = iWsSession->Connect(); |
|
61 if (err != KErrNone) |
|
62 { |
|
63 delete iWsSession; |
|
64 iWsSession = NULL; |
|
65 // Null pointer is used to indicate wserv not present |
|
66 } |
|
67 #endif |
|
68 iTempBuf1.CreateL(256); |
|
69 iTempBuf2.CreateL(256); |
|
70 } |
|
71 |
|
72 TInt CKernListBoxModel::Count() const |
|
73 { |
|
74 return iItemData.Count(); |
|
75 } |
|
76 |
|
77 TInt CKernListBoxModel::ItemIdIndex(TInt aItemId) const |
|
78 { |
|
79 const TInt count = iItemData.Count(); |
|
80 for (TInt i = 0; i < count; i++) |
|
81 { |
|
82 if (iItemData[i]->ItemId() == aItemId) |
|
83 return i; |
|
84 } |
|
85 return KErrNotFound; |
|
86 } |
|
87 |
|
88 CKernListBoxData* CKernListBoxModel::RetrieveDataL(TInt aItemIndex) |
|
89 { |
|
90 iItemData[aItemIndex]->Open(); |
|
91 return iItemData[aItemIndex]; |
|
92 } |
|
93 |
|
94 CKernListBoxData* CKernListBoxModel::RetrieveDataLC(TInt aItemIndex) |
|
95 { |
|
96 CKernListBoxData* data = iItemData[aItemIndex]; |
|
97 data->Open(); |
|
98 CleanupClosePushL(*data); |
|
99 return data; |
|
100 } |
|
101 |
|
102 void CKernListBoxModel::RemoveAllDataL() |
|
103 { |
|
104 const TInt count = iItemData.Count(); |
|
105 for (TInt i = 0; i < count; i++) |
|
106 { |
|
107 iItemData[i]->Close(); |
|
108 } |
|
109 iItemData.Reset(); |
|
110 } |
|
111 |
|
112 void CKernListBoxModel::ModelBeginUpdateLC() |
|
113 { |
|
114 } |
|
115 |
|
116 void CKernListBoxModel::ModelEndUpdateL() |
|
117 { |
|
118 } |
|
119 |
|
120 void CKernListBoxModel::DataUpdatedL(TInt /*aIndex*/) |
|
121 { |
|
122 } |
|
123 |
|
124 TInt CKernListBoxModel::Compare(TInt aLeft, TInt aRight) const |
|
125 { |
|
126 const CKernListBoxData* left = iItemData[aLeft]; |
|
127 const CKernListBoxData* right = iItemData[aRight]; |
|
128 return (*iSort)(left, right); |
|
129 } |
|
130 |
|
131 void CKernListBoxModel::Swap(TInt aLeft,TInt aRight) const |
|
132 { |
|
133 const_cast<CKernListBoxModel*>(this)->WtfSwap(aLeft, aRight); |
|
134 } |
|
135 |
|
136 void CKernListBoxModel::WtfSwap(TInt aLeft,TInt aRight) |
|
137 { |
|
138 CKernListBoxData* temp = iItemData[aLeft]; |
|
139 iItemData[aLeft] = iItemData[aRight]; |
|
140 iItemData[aRight] = temp; |
|
141 } |
|
142 |
|
143 void CKernListBoxModel::RemoveDataL(TInt aItemIndex) |
|
144 { |
|
145 iItemData[aItemIndex]->Close(); |
|
146 iItemData.Remove(aItemIndex); |
|
147 } |
|
148 |
|
149 void CKernListBoxModel::SetCurrentListL(TInt aCurrentList) |
|
150 { |
|
151 if (iCurrentList != aCurrentList) |
|
152 { |
|
153 RemoveAllDataL(); |
|
154 } |
|
155 iCurrentList = aCurrentList; |
|
156 } |
|
157 |
|
158 TInt CKernListBoxModel::GetCurrentList() const |
|
159 { |
|
160 return iCurrentList; |
|
161 } |
|
162 |
|
163 void CKernListBoxModel::NewKernDataL(TInt aType, TObjectKernelInfo* aInfo) |
|
164 { |
|
165 DoNewKernDataL(aType, aInfo, NULL); |
|
166 } |
|
167 |
|
168 void CKernListBoxModel::DoNewKernDataL(TInt aType, TObjectKernelInfo* aInfo, MKernListBoxDataDelegate* aDelegate) |
|
169 { |
|
170 CKernListBoxData* data; |
|
171 switch (aType) |
|
172 { |
|
173 case EListOpenFiles: |
|
174 data = new(ELeave) COpenFilesListBoxData(this); |
|
175 break; |
|
176 case EListThread: |
|
177 data = new(ELeave) CThreadsListBoxData(this); |
|
178 break; |
|
179 case EListFeatureReg: |
|
180 data = new(ELeave) CFeatRegListBoxData(this); |
|
181 break; |
|
182 case EListServer: |
|
183 data = new(ELeave) CServerListBoxData(this); |
|
184 break; |
|
185 case EListHal: |
|
186 data = new(ELeave) CHalListBoxData(this); |
|
187 break; |
|
188 case EListWindowGroups: |
|
189 #ifdef FSHELL_WSERV_SUPPORT |
|
190 data = new(ELeave) CWindowGroupListBoxData(this); |
|
191 #else |
|
192 data = NULL; // Compiler shutter upper |
|
193 User::Leave(KErrNotSupported); |
|
194 #endif |
|
195 break; |
|
196 case EListMessageQueue: |
|
197 data = new(ELeave) CMsgQueListBoxData(this); |
|
198 break; |
|
199 case EListMutex: |
|
200 data = new(ELeave) CMutexListBoxData(this); |
|
201 break; |
|
202 case EListSemaphore: |
|
203 data = new(ELeave) CSemaphoreListBoxData(this); |
|
204 break; |
|
205 case EListTimer: |
|
206 data = new(ELeave) CTimerListBoxData(this); |
|
207 break; |
|
208 default: |
|
209 data = new(ELeave) CKernListBoxData(this); |
|
210 break; |
|
211 } |
|
212 |
|
213 data->SetDelegate(aDelegate); |
|
214 CleanupStack::PushL(data); |
|
215 data->iType = aType; |
|
216 data->ConstructL(); |
|
217 |
|
218 data->FormatL(aInfo, iTempBuf1, iTempBuf2); |
|
219 |
|
220 iItemData.AppendL(data); |
|
221 CleanupStack::Pop(data); |
|
222 data->Open(); // open for model |
|
223 |
|
224 //data->Open(); // open for return |
|
225 data->iInfo = aInfo; |
|
226 //return data; |
|
227 } |
|
228 |
|
229 |
|
230 // This function is used for the list box items |
|
231 void CKernListBoxData::FormatL(TObjectKernelInfo* aInfo, RBuf& aTempBuf1, RBuf& aTempBuf2) |
|
232 { |
|
233 RBuf& name = aTempBuf1; |
|
234 RBuf& more = aTempBuf2; |
|
235 name.Zero(); |
|
236 more.Zero(); |
|
237 |
|
238 TInt itemId = (TInt)aInfo; // By default use the ptr unless the type can suggest anything better |
|
239 DoFormatL(aInfo, aTempBuf1, aTempBuf2, itemId); |
|
240 SetItemId(itemId); |
|
241 |
|
242 if (iDelegate) |
|
243 { |
|
244 iDelegate->FormatChangedL(this, name, more); |
|
245 } |
|
246 } |
|
247 |
|
248 |
|
249 void CKernListBoxData::DoFormatL(TObjectKernelInfo* aInfo, RBuf& name, RBuf& more, TInt& itemId) |
|
250 { |
|
251 switch (iType) |
|
252 { |
|
253 case EListChunk: |
|
254 { |
|
255 TChunkKernelInfo& info = *(TChunkKernelInfo*)aInfo; |
|
256 name.Copy(info.iFullName); |
|
257 PrettyName(iType, name); |
|
258 TBuf<16> size, maxSize; |
|
259 HR(size, info.iSize); |
|
260 HR(maxSize, info.iMaxSize); |
|
261 more.Format(_L("Size %S / %S"), &size, &maxSize); |
|
262 break; |
|
263 } |
|
264 case EListProcess: |
|
265 { |
|
266 TProcessKernelInfo& info = *(TProcessKernelInfo*)aInfo; |
|
267 name.Copy(info.iFullName); |
|
268 PrettyName(iType, name); |
|
269 TUint pid = info.iProcessId; |
|
270 TUint sid = info.iProcessSecurityInfo.iSecureId; |
|
271 TExitType exitType = EExitPending; |
|
272 RProcess proc; |
|
273 if (proc.Open(pid) == KErrNone) |
|
274 { |
|
275 exitType = proc.ExitType(); |
|
276 } |
|
277 if (exitType == EExitPending) |
|
278 { |
|
279 more.Format(_L("Pid %i Sid 0x%x"), pid, sid); |
|
280 } |
|
281 else |
|
282 { |
|
283 TExitCategoryName cat = proc.ExitCategory(); |
|
284 more.Format(_L("Pid %i %S %i Sid 0x%x"), pid, &cat, proc.ExitReason(), sid); |
|
285 } |
|
286 proc.Close(); |
|
287 itemId = pid; |
|
288 break; |
|
289 } |
|
290 case EListCodeSeg: |
|
291 { |
|
292 TTomsciCodeSegKernelInfo& info = *reinterpret_cast<TTomsciCodeSegKernelInfo*>(aInfo); |
|
293 name.Copy(info.iName); |
|
294 |
|
295 TBuf<16> size; |
|
296 HR(size, info.iSize); |
|
297 more.Format(_L("Size %S Ref count %i"), &size, info.iAccessCount); |
|
298 break; |
|
299 } |
|
300 case EListMimeTypes: |
|
301 { |
|
302 SDataType& info = *reinterpret_cast<SDataType*>(aInfo); |
|
303 name.Copy(info.iMime); |
|
304 more.Format(_L("From: %S"), &info.iRecog); |
|
305 break; |
|
306 } |
|
307 default: |
|
308 break; |
|
309 } |
|
310 |
|
311 } |
|
312 |
|
313 void CKernListBoxModel::DumpToCloggerL(RClogger& clogger) |
|
314 { |
|
315 TInt count = Count(); |
|
316 |
|
317 #ifdef __WINS__ |
|
318 clogger.Log("NOTE: This data is from a WINS[CW] build so is not representative of a real device!"); |
|
319 #endif |
|
320 |
|
321 for (TInt i = 0; i < count; i++) |
|
322 { |
|
323 CKernListBoxData* data = static_cast<CKernListBoxData*>(RetrieveDataLC(i)); |
|
324 data->DumpToCloggerL(clogger, i, count); |
|
325 CleanupStack::PopAndDestroy(data); |
|
326 } |
|
327 } |
|
328 |
|
329 void CKernListBoxData::DumpToCloggerL(RClogger& clogger, TInt i, TInt count) |
|
330 { |
|
331 _LIT8(KChunkDesc,"Chunk;FullName;Size;(SizeHumanReadable);MaxSize;(MaxSizeHumanReadable);CreatorPid;BaseAddr"); |
|
332 _LIT8(KChunkFmt,"Chunk;%S;%i;(%S);%i;(%S);%i;%08x"); |
|
333 |
|
334 _LIT8(KProcessDesc,"Process;FullName;Pid;Priority;(PriorityHumanReadable);Sid;Vid;CreatorSid;CreatorName;Capabilities;(CapsHumanReadable);ExitStatus;ExitCategory;ExitReason;FixedProcess;DProcessAddr"); |
|
335 _LIT8(KProcessFmt,"Process;%S;%i;%i;(%S);%x;%x;%x;%S;%x;(%S);%S;%S;%i;%S;%08x"); |
|
336 |
|
337 _LIT8(KCodesegDesc,"CodeSeg;FileName;Size;(SizeHumanReadable);RefCount;DepCount"); |
|
338 _LIT8(KCodesegFmt,"CodeSeg;%S;%i;%S;%i;%i"); |
|
339 |
|
340 _LIT(KMimeDesc,"MimeType;Name;Recogniser;AppUid;AppName"); |
|
341 _LIT(KMimeFmt, "MimeType;%S;%S;%x;%S"); |
|
342 |
|
343 CKernListBoxData* data = this; |
|
344 TObjectKernelInfo* aInfo = data->iInfo; |
|
345 |
|
346 switch (iType) |
|
347 { |
|
348 case EListChunk: |
|
349 { |
|
350 if (i == 0) clogger.Log(KChunkDesc); |
|
351 if (i == 0) |
|
352 { |
|
353 // Also log free at the start, so we can tally up mem losses |
|
354 TInt freeRam = -1, totalRam = -1; |
|
355 TBuf8<16> free, total; |
|
356 HAL::Get(HAL::EMemoryRAMFree, freeRam); |
|
357 HAL::Get(HAL::EMemoryRAM, totalRam); |
|
358 HR(free, freeRam); |
|
359 HR(total, totalRam); |
|
360 _LIT8(KFree, "FREE"); |
|
361 clogger.Log(KChunkFmt, &KFree, freeRam, &free, totalRam, &total, 0); |
|
362 } |
|
363 |
|
364 TChunkKernelInfo& info = *(TChunkKernelInfo*)aInfo; |
|
365 TBuf8<16> size, maxSize; |
|
366 HR(size, info.iSize); |
|
367 HR(maxSize, info.iMaxSize); |
|
368 clogger.Log(KChunkFmt, &info.iFullName, info.iSize, &size, info.iMaxSize, &maxSize, info.iControllingOwnerProcessId, info.iBase); |
|
369 |
|
370 if (i == count-1) |
|
371 { |
|
372 // Also print out free RAM at end, so we can see if mem usage changed much during |
|
373 TInt freeRam = -1, totalRam = -1; |
|
374 TBuf8<16> free, total; |
|
375 HAL::Get(HAL::EMemoryRAMFree, freeRam); |
|
376 HAL::Get(HAL::EMemoryRAM, totalRam); |
|
377 HR(free, freeRam); |
|
378 HR(total, totalRam); |
|
379 _LIT8(KFree, "FREE"); |
|
380 clogger.Log(KChunkFmt, &KFree, freeRam, &free, totalRam, &total, 0); |
|
381 } |
|
382 break; |
|
383 } |
|
384 case EListProcess: |
|
385 { |
|
386 if (i == 0) clogger.Log(KProcessDesc); |
|
387 TProcessKernelInfo& info = *(TProcessKernelInfo*)aInfo; |
|
388 |
|
389 TBuf<16> priority16 = ToString((TProcessPriority)info.iPriority); |
|
390 TPtr8 priority = priority16.Collapse(); |
|
391 HBufC* caps16 = ToStringL(info.iProcessSecurityInfo.iCaps); |
|
392 TPtr8 caps(caps16->Des().Collapse()); |
|
393 TPtrC exitStatus; |
|
394 TInt exitReason = 0; |
|
395 TExitCategoryName exitCategory; |
|
396 RProcess handle; |
|
397 if (handle.Open(info.iProcessId) == KErrNone) |
|
398 { |
|
399 exitStatus.Set(ToString(handle.ExitType())); |
|
400 exitCategory = handle.ExitCategory(); |
|
401 exitReason = handle.ExitReason(); |
|
402 handle.Close(); |
|
403 } |
|
404 TBuf8<16> exitStatus8; |
|
405 exitStatus8.Copy(exitStatus); |
|
406 TPtrC8 exitCategory8 = exitCategory.Collapse(); |
|
407 RBuf creatorName; |
|
408 data->ExeNameForSid(info.iProcessCreatorSecurityInfo.iSecureId, creatorName); |
|
409 TPtrC8 creatorName8 = creatorName.Collapse(); |
|
410 TBool fixed = info.iAttributes & 1; // TMemModelProcessAttributes::EFixedAddress |
|
411 _LIT8(KFixed, "FIXED"); |
|
412 TPtrC8 fixedPtr = fixed ? KFixed() : KNullDesC8(); |
|
413 clogger.Log(KProcessFmt, &info.iFullName, info.iProcessId, info.iPriority, &priority, info.iProcessSecurityInfo.iSecureId, info.iProcessSecurityInfo.iVendorId, info.iProcessCreatorSecurityInfo.iSecureId, &creatorName8, info.iProcessSecurityInfo.iCaps[0], &caps, &exitStatus8, &exitCategory8, exitReason, &fixedPtr, info.iAddressOfKernelObject); |
|
414 creatorName.Close(); |
|
415 delete caps16; |
|
416 break; |
|
417 } |
|
418 case EListCodeSeg: |
|
419 { |
|
420 if (i == 0) clogger.Log(KCodesegDesc); |
|
421 TTomsciCodeSegKernelInfo& info = *reinterpret_cast<TTomsciCodeSegKernelInfo*>(aInfo); |
|
422 TBuf8<16> size; |
|
423 HR(size, info.iSize); |
|
424 clogger.Log(KCodesegFmt, &info.iName, info.iSize, &size, info.iAccessCount, info.iDepCount); |
|
425 break; |
|
426 } |
|
427 case EListMimeTypes: |
|
428 { |
|
429 if (i == 0) clogger.Log(KMimeDesc); |
|
430 SDataType& info = *reinterpret_cast<SDataType*>(aInfo); |
|
431 clogger.Log(KMimeFmt, &info.iMime, &info.iRecog, info.iAppUid, &info.iApp); |
|
432 break; |
|
433 } |
|
434 default: |
|
435 break; |
|
436 } |
|
437 } |
|
438 |
|
439 void CKernListBoxData::InfoForDialogL(RBuf& aTitle, RBuf& aText, TBool aRefresh) |
|
440 { |
|
441 if (aRefresh) |
|
442 { |
|
443 // Figure out our index in the model |
|
444 TInt index = iModel->ItemIdIndex(ItemId()); |
|
445 iModel->RefreshDataL(index); |
|
446 } |
|
447 |
|
448 aTitle.Zero(); |
|
449 aText.Zero(); |
|
450 |
|
451 if (aTitle.MaxLength() < 256) |
|
452 { |
|
453 aTitle.ReAllocL(256); |
|
454 } |
|
455 if (aText.MaxLength() < 1024) |
|
456 { |
|
457 aText.ReAllocL(1024); |
|
458 } |
|
459 |
|
460 RBuf& inf = aText; |
|
461 TBuf<256>* name = new(ELeave) TBuf<256>; |
|
462 CleanupStack::PushL(name); |
|
463 DoInfoForDialogL(aTitle, inf, name); |
|
464 CleanupStack::PopAndDestroy(name); |
|
465 } |
|
466 |
|
467 void AppendProcessFlags(TDes& aBuf, TUint32 aFlags) |
|
468 { |
|
469 TInt len = aBuf.Length(); |
|
470 |
|
471 // 9.1/9.2 doesn't have these, it's easier to redefine them to the correct value than make all the code conditional |
|
472 const TUint KThreadFlagRealtime = 0x00000040; |
|
473 const TUint KThreadFlagRealtimeTest = 0x00000080; |
|
474 |
|
475 #define IF_MATCH(aBuf, aFlags, aFlag) if (aFlags&aFlag) { aBuf.Append(_L( #aFlag )); aBuf.Append('|'); } |
|
476 IF_MATCH(aBuf, aFlags, KThreadFlagProcessCritical) |
|
477 IF_MATCH(aBuf, aFlags, KThreadFlagProcessPermanent) |
|
478 IF_MATCH(aBuf, aFlags, KThreadFlagSystemCritical) |
|
479 IF_MATCH(aBuf, aFlags, KThreadFlagSystemPermanent) |
|
480 IF_MATCH(aBuf, aFlags, KThreadFlagOriginal) |
|
481 IF_MATCH(aBuf, aFlags, KThreadFlagLastChance) |
|
482 IF_MATCH(aBuf, aFlags, KThreadFlagRealtime) |
|
483 IF_MATCH(aBuf, aFlags, KThreadFlagRealtimeTest) |
|
484 IF_MATCH(aBuf, aFlags, KProcessFlagPriorityControl) |
|
485 IF_MATCH(aBuf, aFlags, KProcessFlagJustInTime) |
|
486 if (aBuf.Length() > len) |
|
487 { |
|
488 // Remove trailing | |
|
489 aBuf.SetLength(aBuf.Length() - 1); |
|
490 } |
|
491 } |
|
492 |
|
493 void CKernListBoxData::DoInfoForDialogL(RBuf& aTitle, RBuf& inf, TDes* aTemp) |
|
494 { |
|
495 TDes* name = aTemp; |
|
496 switch (iType) |
|
497 { |
|
498 case EListProcess: |
|
499 { |
|
500 TProcessKernelInfo& info = *(TProcessKernelInfo*)iInfo; |
|
501 RProcess process; |
|
502 TInt err = process.Open(info.iProcessId); |
|
503 CleanupClosePushL(process); |
|
504 |
|
505 _LIT(KInfo, "Process info"); |
|
506 aTitle.Copy(KInfo); |
|
507 inf.Copy(iInfo->iFullName); |
|
508 if (!err) |
|
509 { |
|
510 inf.Append(Klf); |
|
511 inf.Append(process.FileName()); |
|
512 } |
|
513 if (info.iCommandLine.Length()) |
|
514 { |
|
515 inf.Append(' '); |
|
516 //aTemp->Copy(info.iCommandLine); |
|
517 // Command line args are generally 16-bit descriptors even though they're represented in 8-bit kernel-side |
|
518 TPtrC widePtr((const TUint16*)info.iCommandLine.Ptr(), info.iCommandLine.Size()/2); |
|
519 inf.Append(widePtr); |
|
520 } |
|
521 |
|
522 //_LIT8(KProcessDesc, "Process\tFullName\tPid\tPriority\t(PriorityHumanReadable)\tSid\tVid\tCapabilities\t(CapsHumanReadable)\tExitStatus\tExitCategory\tExitReason"); |
|
523 |
|
524 _LIT(KProcess, "\n\nPid: %i %S\nSid: 0x%x Vid: 0x%x"); |
|
525 _LIT(KPriority, "\nPriority: %i (%S)"); |
|
526 _LIT(KOtherStuff, "\nCreator Sid: 0x%x (%S)\n\nCapabilities: %S"); |
|
527 _LIT(KKern, "\nKernel object address: 0x%08x"); |
|
528 _LIT(KFlags, "\nFlags: 0x%x ("); |
|
529 _LIT(KDied, "\n\nDied with: %S %S %i"); |
|
530 |
|
531 HBufC* caps = ToStringL(info.iProcessSecurityInfo.iCaps); |
|
532 TUint creatorSid = info.iProcessCreatorSecurityInfo.iSecureId; |
|
533 TBool fixed = info.iAttributes & 1; // TMemModelProcessAttributes::EFixedAddress |
|
534 _LIT(KFixed, "(fixed process)"); |
|
535 TPtrC fixedPtr = fixed ? KFixed() : KNullDesC(); |
|
536 inf.AppendFormat(KProcess, info.iProcessId, &fixedPtr, info.iProcessSecurityInfo.iSecureId, info.iProcessSecurityInfo.iVendorId); |
|
537 if (!err) |
|
538 { |
|
539 TPtrC priority = ToString(process.Priority()); |
|
540 inf.AppendFormat(KPriority, process.Priority(), &priority); |
|
541 } |
|
542 inf.AppendFormat(KKern, info.iAddressOfKernelObject); |
|
543 if (info.iFlags) |
|
544 { |
|
545 inf.AppendFormat(KFlags, info.iFlags); |
|
546 AppendProcessFlags(inf, info.iFlags); |
|
547 inf.Append(')'); |
|
548 } |
|
549 |
|
550 RBuf parentName; |
|
551 ExeNameForSid(creatorSid, parentName); |
|
552 |
|
553 inf.AppendFormat(KOtherStuff, creatorSid, &parentName, caps); |
|
554 delete caps; |
|
555 parentName.Close(); |
|
556 |
|
557 if (!err && process.ExitType() != EExitPending) |
|
558 { |
|
559 TPtrC exitStatus; |
|
560 TInt exitReason = 0; |
|
561 TExitCategoryName exitCategory; |
|
562 exitStatus.Set(ToString(process.ExitType())); |
|
563 if (process.ExitType() == EExitPanic) |
|
564 { |
|
565 exitCategory = process.ExitCategory(); |
|
566 } |
|
567 exitReason = process.ExitReason(); |
|
568 inf.AppendFormat(KDied, &exitStatus, &exitCategory, exitReason); |
|
569 } |
|
570 CleanupStack::PopAndDestroy(&process); |
|
571 break; |
|
572 } |
|
573 case EListChunk: |
|
574 { |
|
575 TChunkKernelInfo& info = *(TChunkKernelInfo*)iInfo; |
|
576 _LIT(KInfo, "Chunk info"); |
|
577 aTitle.Copy(KInfo); |
|
578 inf.Copy(iInfo->iFullName); |
|
579 inf.Append(Klflf); |
|
580 |
|
581 TBuf<16> size, maxSize; |
|
582 HR(size, info.iSize); |
|
583 HR(maxSize, info.iMaxSize); |
|
584 |
|
585 RProcess creator; |
|
586 TInt err = creator.Open(info.iControllingOwnerProcessId); |
|
587 if (!err) |
|
588 { |
|
589 *name = creator.FullName(); |
|
590 PrettyName(EListProcess, *name); |
|
591 creator.Close(); |
|
592 } |
|
593 _LIT(KKern, "Kernel object address: 0x%08x\n"); |
|
594 _LIT(KChunk, "Base: 0x%08x\nSize: %S\nMax Size: %S\nCreator pid: %i (%S)"); |
|
595 inf.AppendFormat(KKern, info.iAddressOfKernelObject); |
|
596 inf.AppendFormat(KChunk, info.iBase, &size, &maxSize, info.iControllingOwnerProcessId, name); |
|
597 break; |
|
598 } |
|
599 case EListCodeSeg: |
|
600 { |
|
601 TTomsciCodeSegKernelInfo& info = *reinterpret_cast<TTomsciCodeSegKernelInfo*>(iInfo); |
|
602 _LIT(KInfo, "Code segment info"); |
|
603 aTitle.Copy(KInfo); |
|
604 inf.Copy(info.iName); |
|
605 inf.Append(Klflf); |
|
606 |
|
607 TBuf<16> size; |
|
608 HR(size, info.iSize); |
|
609 _LIT(KCodesegFmt, "File name: %S\nSize %S\nRef count %i\nDependancy count %i\nRun address 0x%08x"); |
|
610 aTemp->Copy(info.iFileName); |
|
611 inf.AppendFormat(KCodesegFmt, aTemp, &size, info.iAccessCount, info.iDepCount, info.iRunAddress); |
|
612 break; |
|
613 } |
|
614 case EListMimeTypes: |
|
615 { |
|
616 SDataType& info = *reinterpret_cast<SDataType*>(iInfo); |
|
617 _LIT(KInfo, "Mime type info"); |
|
618 aTitle.Copy(KInfo); |
|
619 |
|
620 inf.AppendFormat(_L("%S\n\n%S\nApp UID: 0x%x\n%S"), &info.iMime, &info.iRecog, info.iAppUid, &info.iApp); |
|
621 break; |
|
622 } |
|
623 default: |
|
624 break; |
|
625 } |
|
626 } |
|
627 |
|
628 void CKernListBoxModel::SummaryInfoL(TDes& aBuf) |
|
629 { |
|
630 switch (iCurrentList) |
|
631 { |
|
632 case EListProcess: |
|
633 { |
|
634 _LIT(KFmt, "%i processes"); |
|
635 aBuf.Format(KFmt, Count()); |
|
636 break; |
|
637 } |
|
638 case EListThread: |
|
639 { |
|
640 _LIT(KFmt, "%i threads"); |
|
641 aBuf.Format(KFmt, Count()); |
|
642 break; |
|
643 } |
|
644 case EListChunk: |
|
645 { |
|
646 _LIT(KFmt, "%i chunks, free %S/%S"); |
|
647 TInt freeRam = -1, totalRam = -1; |
|
648 TBuf<16> free, total; |
|
649 HAL::Get(HAL::EMemoryRAMFree, freeRam); |
|
650 HAL::Get(HAL::EMemoryRAM, totalRam); |
|
651 HR(free, freeRam); |
|
652 HR(total, totalRam); |
|
653 aBuf.Format(KFmt, Count(), &free, &total); |
|
654 break; |
|
655 } |
|
656 case EListCodeSeg: |
|
657 { |
|
658 _LIT(KFmt, "%i code segments"); |
|
659 aBuf.Format(KFmt, Count()); |
|
660 break; |
|
661 } |
|
662 case EListHal: |
|
663 { |
|
664 _LIT(KFmt, "%i HAL attributes"); |
|
665 aBuf.Format(KFmt, Count()); |
|
666 break; |
|
667 } |
|
668 case EListWindowGroups: |
|
669 { |
|
670 _LIT(KFmt, "%i window groups"); |
|
671 aBuf.Format(KFmt, Count()); |
|
672 break; |
|
673 } |
|
674 case EListMimeTypes: |
|
675 { |
|
676 _LIT(KFmt, "%i mime types"); |
|
677 aBuf.Format(KFmt, Count()); |
|
678 break; |
|
679 } |
|
680 case EListOpenFiles: |
|
681 { |
|
682 _LIT(KFmt, "%i open files"); |
|
683 aBuf.Format(KFmt, Count()); |
|
684 break; |
|
685 } |
|
686 case EListFeatureReg: |
|
687 { |
|
688 _LIT(KFmt, "%i features in registry"); |
|
689 aBuf.Format(KFmt, Count()); |
|
690 break; |
|
691 } |
|
692 case EListServer: |
|
693 { |
|
694 _LIT(KFmt, "%i servers"); |
|
695 aBuf.Format(KFmt, Count()); |
|
696 break; |
|
697 } |
|
698 case EListMessageQueue: |
|
699 { |
|
700 _LIT(KFmt, "%i message queues"); |
|
701 aBuf.Format(KFmt, Count()); |
|
702 break; |
|
703 } |
|
704 case EListMutex: |
|
705 { |
|
706 _LIT(KFmt, "%i mutexes"); |
|
707 aBuf.Format(KFmt, Count()); |
|
708 break; |
|
709 } |
|
710 case EListSemaphore: |
|
711 { |
|
712 _LIT(KFmt, "%i semaphores"); |
|
713 aBuf.Format(KFmt, Count()); |
|
714 break; |
|
715 } |
|
716 case EListTimer: |
|
717 { |
|
718 _LIT(KFmt, "%i timers"); |
|
719 aBuf.Format(KFmt, Count()); |
|
720 break; |
|
721 } |
|
722 default: |
|
723 break; |
|
724 } |
|
725 } |
|
726 |
|
727 TBool CKernListBoxData::SupportsCommand(TInt aCommand) |
|
728 { |
|
729 switch (aCommand) |
|
730 { |
|
731 case ECmdPoll: |
|
732 case ECmdHandleInfo: |
|
733 { |
|
734 if (iType == EListProcess || iType == EListChunk) return ETrue; |
|
735 break; |
|
736 } |
|
737 case ECmdKill: |
|
738 { |
|
739 if (iType == EListProcess) return ETrue; |
|
740 break; |
|
741 } |
|
742 default: |
|
743 break; |
|
744 } |
|
745 return EFalse; |
|
746 } |
|
747 |
|
748 void CKernListBoxData::KillL() |
|
749 { |
|
750 TUint8* addr = iInfo->iAddressOfKernelObject; |
|
751 RMemoryAccess& mem = iModel->MemAccess(); |
|
752 User::LeaveIfError(mem.ObjectDie(iType == EListThread ? EThread : EProcess, 0, addr, EExitKill, 666999, KNullDesC)); |
|
753 // The undertaker should cause an update via ThreadDiedL |
|
754 } |
|
755 |
|
756 TAny* CKernListBoxData::GetHandleL() |
|
757 { |
|
758 return iInfo->iAddressOfKernelObject; |
|
759 } |
|
760 |
|
761 TInt CKernListBoxData::ExeNameForSid(TUint aSid, RBuf& aName) |
|
762 { |
|
763 // First try our list |
|
764 TInt lserr = KErrNotFound; |
|
765 if (aName.Create(256) != KErrNone) lserr = KErrNoMemory; |
|
766 if (iModel && aName.MaxLength()) |
|
767 { |
|
768 for (TInt i = 0; i < iModel->iItemData.Count(); i++) |
|
769 { |
|
770 CKernListBoxData* data = static_cast<CKernListBoxData*>(iModel->iItemData[i]); |
|
771 TProcessKernelInfo* pinfo = static_cast<TProcessKernelInfo*>(data->iInfo); |
|
772 if (data->iType == EListProcess && pinfo->iProcessSecurityInfo.iSecureId == aSid) |
|
773 { |
|
774 lserr = KErrNone; |
|
775 aName.Copy(pinfo->iName); |
|
776 PrettyName(EListProcess, aName); |
|
777 break; |
|
778 } |
|
779 } |
|
780 } |
|
781 #ifdef FSHELL_APPARC_SUPPORT |
|
782 if (lserr == KErrNotFound) |
|
783 { |
|
784 // Didn't find the process in our process list. Must have already closed. Try |
|
785 // apparc as a fallback - will only work for fully-fledged applications |
|
786 RApaLsSession ls; |
|
787 TInt lserr = ls.Connect(); |
|
788 TApaAppInfo* appinfo = new TApaAppInfo; |
|
789 if (!appinfo ) lserr = KErrNoMemory; |
|
790 if (!lserr) |
|
791 { |
|
792 lserr = ls.GetAppInfo(*appinfo , TUid::Uid(aSid)); |
|
793 } |
|
794 if (!lserr) |
|
795 { |
|
796 TInt slash = appinfo->iFullName.LocateReverse('\\'); |
|
797 aName.Copy(appinfo->iFullName.Mid(slash+1)); |
|
798 } |
|
799 delete appinfo; |
|
800 ls.Close(); |
|
801 } |
|
802 #endif |
|
803 |
|
804 if (aName.Length() == 0 && aSid == 0x10205c44) |
|
805 { |
|
806 // Special case this because sysstart isn't running & isn't an app, and appears |
|
807 // enough as parent to be worth special-casing |
|
808 aName.Copy(_L("SysStart")); |
|
809 lserr = KErrNone; |
|
810 } |
|
811 return lserr; |
|
812 } |
|
813 |
|
814 void CKernListBoxModel::ThreadDiedL(TInt aHandle) |
|
815 { |
|
816 RThread thread; |
|
817 thread.SetHandle(aHandle); |
|
818 TThreadId id = thread.Id(); |
|
819 iThreadHandleArray.Append(aHandle); |
|
820 |
|
821 if (iCurrentList == EListThread) |
|
822 { |
|
823 TInt idx = ItemIdIndex(id); |
|
824 if (idx != KErrNotFound) |
|
825 { |
|
826 ModelBeginUpdateLC(); |
|
827 CKernListBoxData* data = static_cast<CKernListBoxData*>(iItemData[idx]); |
|
828 data->FormatL(data->iInfo, iTempBuf1, iTempBuf2); // Thread death info isn't stored in iInfo, so no need to update it |
|
829 DataUpdatedL(idx); |
|
830 ModelEndUpdateL(); |
|
831 |
|
832 if (iInfoChangedCallback.iFunction != NULL && data == iCallbackData) |
|
833 { |
|
834 iInfoChangedCallback.CallBack(); |
|
835 } |
|
836 |
|
837 } |
|
838 else |
|
839 { |
|
840 // We don't have an entry for this thread id. Oh well, just storing it in the tid list will guarantee it will still be there when the user hits refresh |
|
841 } |
|
842 } |
|
843 else if (iCurrentList == EListProcess) |
|
844 { |
|
845 RProcess p; |
|
846 if (thread.Process(p) == KErrNone) |
|
847 { |
|
848 TProcessId id = p.Id(); |
|
849 TInt idx = ItemIdIndex(id); |
|
850 p.Close(); |
|
851 if (idx != KErrNotFound) |
|
852 { |
|
853 ModelBeginUpdateLC(); |
|
854 CKernListBoxData* data = static_cast<CKernListBoxData*>(iItemData[idx]); |
|
855 data->FormatL(data->iInfo, iTempBuf1, iTempBuf2); // Process death info isn't stored in iInfo, so no need to update it |
|
856 DataUpdatedL(idx); |
|
857 ModelEndUpdateL(); |
|
858 if (iInfoChangedCallback.iFunction != NULL && data == iCallbackData) |
|
859 { |
|
860 iInfoChangedCallback.CallBack(); |
|
861 } |
|
862 |
|
863 } |
|
864 } |
|
865 } |
|
866 } |
|
867 |
|
868 void CKernListBoxModel::CloseAllThreadHandles() |
|
869 { |
|
870 for (TInt i = 0; i < iThreadHandleArray.Count(); i++) |
|
871 { |
|
872 RThread t; |
|
873 t.SetHandle(iThreadHandleArray[i]); |
|
874 t.Close(); |
|
875 } |
|
876 iThreadHandleArray.Reset(); |
|
877 } |
|
878 |
|
879 CKernListBoxModel::~CKernListBoxModel() |
|
880 { |
|
881 CloseAllThreadHandles(); |
|
882 delete iUnd; |
|
883 #ifdef FSHELL_WSERV_SUPPORT |
|
884 if (iWsSession) |
|
885 { |
|
886 iWsSession->Close(); |
|
887 delete iWsSession; |
|
888 } |
|
889 #endif |
|
890 iTempBuf1.Close(); |
|
891 iTempBuf2.Close(); |
|
892 |
|
893 for (TInt i = iItemData.Count()-1; i >= 0; i--) |
|
894 { |
|
895 iItemData[i]->Close(); |
|
896 } |
|
897 iItemData.Close(); |
|
898 } |
|
899 |
|
900 CUndertaker::CUndertaker(CKernListBoxModel& aModel) |
|
901 : CActive(EPriorityStandard), iModel(aModel) |
|
902 { |
|
903 CActiveScheduler::Add(this); |
|
904 } |
|
905 |
|
906 CUndertaker::~CUndertaker() |
|
907 { |
|
908 Cancel(); |
|
909 iUnd.Close(); |
|
910 } |
|
911 |
|
912 void CUndertaker::Register() |
|
913 { |
|
914 TInt err = KErrNone; |
|
915 if (!iUnd.Handle()) |
|
916 { |
|
917 err = iUnd.Create(); |
|
918 } |
|
919 if (!err) |
|
920 { |
|
921 iUnd.Logon(iStatus, iHandle); |
|
922 SetActive(); |
|
923 } |
|
924 } |
|
925 |
|
926 void CUndertaker::RunL() |
|
927 { |
|
928 if (iStatus == KErrDied) |
|
929 { |
|
930 iModel.ThreadDiedL(iHandle); |
|
931 Register(); |
|
932 } |
|
933 } |
|
934 |
|
935 void CUndertaker::DoCancel() |
|
936 { |
|
937 iUnd.LogonCancel(); |
|
938 } |
|
939 |
|
940 void CKernListBoxModel::RefreshDataL(TInt aIndex) |
|
941 { |
|
942 if (iCurrentList == EListWindowGroups && !iWsSession) |
|
943 { |
|
944 User::Leave(KErrNotSupported); |
|
945 } |
|
946 |
|
947 // Change some names so the code is the same |
|
948 RMemoryAccess& mem(iMemAccess); |
|
949 CKernListBoxModel& model(*this); |
|
950 |
|
951 if (iCurrentList == EListCodeSeg) |
|
952 { |
|
953 // Code segs don't support random access |
|
954 aIndex = -1; |
|
955 } |
|
956 |
|
957 if (aIndex == -1) |
|
958 { |
|
959 model.RemoveAllDataL(); |
|
960 } |
|
961 model.ModelBeginUpdateLC(); |
|
962 |
|
963 TObjectType type = EProcess; // Just set it to something to shut up compiler |
|
964 switch (iCurrentList) { |
|
965 case EListProcess: type = EProcess; break; |
|
966 case EListThread: type = EThread; break; |
|
967 case EListChunk: type = EChunk; break; |
|
968 case EListServer: type = EServer; break; |
|
969 case EListMessageQueue: type = EMsgQueue; break; |
|
970 case EListMutex: type = EMutex; break; |
|
971 case EListSemaphore: type = ESemaphore; break; |
|
972 case EListTimer: type = ETimer; break; |
|
973 default: break; |
|
974 } |
|
975 |
|
976 TPtr8 buf(0,0); |
|
977 TObjectKernelInfo* info = NULL; |
|
978 CKernListBoxData* data = NULL; |
|
979 if (aIndex != -1) |
|
980 { |
|
981 data = static_cast<CKernListBoxData*>(model.RetrieveDataL(aIndex)); |
|
982 CleanupClosePushL(*data); |
|
983 } |
|
984 |
|
985 if (iCurrentList == EListCodeSeg) |
|
986 { |
|
987 mem.AcquireCodeSegMutex(); |
|
988 TTomsciCodeSegKernelInfo* inf = new(ELeave) TTomsciCodeSegKernelInfo; |
|
989 info = reinterpret_cast<TObjectKernelInfo*>(inf); // These aren't actually related classes, just convenient |
|
990 buf.Set(TPckg<TTomsciCodeSegKernelInfo>(*inf)); |
|
991 while (mem.GetNextCodeSegInfo(buf) == KErrNone) |
|
992 { |
|
993 TRAPD(err, model.NewKernDataL(iCurrentList, info)); |
|
994 if (err) |
|
995 { |
|
996 break; |
|
997 } |
|
998 inf = NULL; |
|
999 inf = new(ELeave) TTomsciCodeSegKernelInfo; |
|
1000 buf.Set(TPckg<TTomsciCodeSegKernelInfo>(*inf)); |
|
1001 info = reinterpret_cast<TObjectKernelInfo*>(inf); // These aren't actually related classes, just convenient |
|
1002 } |
|
1003 delete inf; |
|
1004 mem.ReleaseCodeSegMutex(); |
|
1005 } |
|
1006 else if (iCurrentList == EListHal) |
|
1007 { |
|
1008 // HAL isn't actually a kernel container type but from the PoV of this app it is treated similarly |
|
1009 //HAL::SEntry* entry = new(ELeave) HAL::SEntry; |
|
1010 if (aIndex == -1) |
|
1011 { |
|
1012 HAL::SEntry* ents = NULL; |
|
1013 TInt numEntries = 0; |
|
1014 User::LeaveIfError(HAL::GetAll(numEntries, ents)); |
|
1015 CleanupDeletePushL(ents); |
|
1016 for (TInt i = 0; i < numEntries; i++) |
|
1017 { |
|
1018 SHalInfo* entry = new(ELeave) SHalInfo; |
|
1019 entry->iProperties = ents[i].iProperties; |
|
1020 entry->iValue = ents[i].iValue; |
|
1021 entry->iAttribute = i; |
|
1022 CleanupDeletePushL(entry); |
|
1023 model.NewKernDataL(iCurrentList, reinterpret_cast<TObjectKernelInfo*>(entry)); |
|
1024 CleanupStack::Pop(entry); |
|
1025 } |
|
1026 CleanupStack::PopAndDestroy(ents); |
|
1027 } |
|
1028 else |
|
1029 { |
|
1030 SHalInfo* entry = reinterpret_cast<SHalInfo*>(data->iInfo); |
|
1031 /*TInt err =*/ HAL::Get((HAL::TAttribute)entry->iAttribute, entry->iValue); // Nothing needs to be done if this fails |
|
1032 } |
|
1033 } |
|
1034 else if (iCurrentList == EListWindowGroups) |
|
1035 { |
|
1036 #if defined(FSHELL_WSERV_SUPPORT) && defined(FSHELL_APPARC_SUPPORT) |
|
1037 if (aIndex == -1) |
|
1038 { |
|
1039 CArrayFixFlat<TInt>* wgIds = new(ELeave) CArrayFixFlat<TInt>(16); |
|
1040 CleanupStack::PushL(wgIds); |
|
1041 User::LeaveIfError(iWsSession->WindowGroupList(0, wgIds)); |
|
1042 TInt numEntries = wgIds->Count(); |
|
1043 for (TInt i = 0; i < numEntries; i++) |
|
1044 { |
|
1045 TInt handle = (*wgIds)[i]; |
|
1046 CApaWindowGroupName* name = CApaWindowGroupName::NewLC(*iWsSession, handle); |
|
1047 SWgInfo* info = new(ELeave) SWgInfo; |
|
1048 CleanupStack::PushL(info); |
|
1049 info->iHandle = handle; |
|
1050 info->iName = name; |
|
1051 info->iSession = iWsSession; |
|
1052 model.NewKernDataL(iCurrentList, reinterpret_cast<TObjectKernelInfo*>(info)); |
|
1053 CleanupStack::Pop(2, name); // info, name |
|
1054 } |
|
1055 CleanupStack::PopAndDestroy(wgIds); |
|
1056 } |
|
1057 else |
|
1058 { |
|
1059 SWgInfo* info = reinterpret_cast<SWgInfo*>(data->iInfo); |
|
1060 info->iName->ConstructFromWgIdL(info->iHandle); |
|
1061 } |
|
1062 #endif |
|
1063 } |
|
1064 else if (iCurrentList == EListMimeTypes) |
|
1065 { |
|
1066 if (aIndex == -1) |
|
1067 { |
|
1068 #ifdef FSHELL_APPARC_SUPPORT |
|
1069 RApaLsSession apparc; |
|
1070 User::LeaveIfError(apparc.Connect()); |
|
1071 CleanupClosePushL(apparc); |
|
1072 RImplInfoPtrArray array; |
|
1073 CleanupResetAndDestroyPushL(array); |
|
1074 REComSession::ListImplementationsL(TUid::Uid(0x101F7D87), array); // Recognisers ECOM interface UID |
|
1075 TFileName* dllNamePtr = new(ELeave)TFileName; |
|
1076 CleanupStack::PushL(dllNamePtr); |
|
1077 TFileName& dllName = *dllNamePtr; |
|
1078 RArray<TDataType> mimeTypes; |
|
1079 CleanupClosePushL(mimeTypes); |
|
1080 gPlugin->DisablePanicCheckPushL(); |
|
1081 for (TInt i = 0; i < array.Count(); i++) |
|
1082 { |
|
1083 dllName = _L("UnknownDll"); |
|
1084 |
|
1085 TRAP_IGNORE(Sandbox::GetDllNameFromEcomUidL(mem, array[i]->ImplementationUid(), dllName)); |
|
1086 mimeTypes.Reset(); |
|
1087 Sandbox::GetRecogniserInfoL(array[i]->ImplementationUid(), mimeTypes); |
|
1088 |
|
1089 TInt count = mimeTypes.Count(); |
|
1090 for (TInt j = 0; j < count; j++) |
|
1091 { |
|
1092 SDataType* info = new(ELeave) SDataType; |
|
1093 CleanupStack::PushL(info); |
|
1094 info->iMime.Copy(mimeTypes[j].Des8()); |
|
1095 info->iRecog = dllName; |
|
1096 |
|
1097 TInt err = apparc.AppForDataType(mimeTypes[j], info->iAppUid); |
|
1098 if (!err) |
|
1099 { |
|
1100 TApaAppInfo appInfo; |
|
1101 err = apparc.GetAppInfo(appInfo, info->iAppUid); |
|
1102 if (!err) |
|
1103 { |
|
1104 info->iApp = appInfo.iFullName; |
|
1105 } |
|
1106 } |
|
1107 model.NewKernDataL(iCurrentList, reinterpret_cast<TObjectKernelInfo*>(info)); |
|
1108 CleanupStack::Pop(info); |
|
1109 } |
|
1110 } |
|
1111 CleanupStack::PopAndDestroy(); // reenables panic checks |
|
1112 CleanupStack::PopAndDestroy(4, &apparc); // mimeTypes, dllNamePtr, array, apparc |
|
1113 #else |
|
1114 User::Leave(KErrNotSupported); |
|
1115 #endif |
|
1116 } |
|
1117 else |
|
1118 { |
|
1119 // No refreshing necessary for mime types |
|
1120 } |
|
1121 } |
|
1122 else if (iCurrentList == EListOpenFiles) |
|
1123 { |
|
1124 if (aIndex == -1) |
|
1125 { |
|
1126 RPtrHashMap<TDesC, SOpenFile> fileMap; |
|
1127 CleanupClosePushL(fileMap); |
|
1128 RFs fs; |
|
1129 User::LeaveIfError(fs.Connect()); |
|
1130 CleanupClosePushL(fs); |
|
1131 TOpenFileScan scan(fs); |
|
1132 CFileList* fileList = NULL; |
|
1133 FOREVER |
|
1134 { |
|
1135 scan.NextL(fileList); |
|
1136 if (fileList == NULL) |
|
1137 { |
|
1138 break; |
|
1139 } |
|
1140 CleanupStack::PushL(fileList); |
|
1141 const TInt numOpenFiles = fileList->Count(); |
|
1142 for (TInt i = 0; i < numOpenFiles; i++) |
|
1143 { |
|
1144 const TEntry& entry = (*fileList)[i]; |
|
1145 // See if we already have an SOpenFile for this filename |
|
1146 SOpenFile* info = fileMap.Find(entry.iName); |
|
1147 if (info) |
|
1148 { |
|
1149 if (info->iNumThreads < info->iThreadIds.Count()) |
|
1150 { |
|
1151 info->iThreadIds[info->iNumThreads] = scan.ThreadId(); |
|
1152 } |
|
1153 info->iNumThreads++; // Increment iNumThreads regardless - so we can see how many threads there actually are, rather than how many we can store |
|
1154 CKernListBoxData* data = static_cast<CKernListBoxData*>(model.RetrieveDataLC(model.ItemIdIndex((TInt)info))); |
|
1155 data->FormatL(reinterpret_cast<TObjectKernelInfo*>(info), iTempBuf1, iTempBuf2); // now we've updated the number of threads, that will have changed the Format view |
|
1156 CleanupStack::PopAndDestroy(data); |
|
1157 } |
|
1158 else |
|
1159 { |
|
1160 SOpenFile* info = new(ELeave) SOpenFile; |
|
1161 CleanupStack::PushL(info); |
|
1162 info->iName = entry.iName; |
|
1163 info->iNumThreads = 1; |
|
1164 info->iThreadIds[0] = scan.ThreadId(); |
|
1165 model.NewKernDataL(iCurrentList, reinterpret_cast<TObjectKernelInfo*>(info)); |
|
1166 CleanupStack::Pop(info); |
|
1167 fileMap.InsertL(&info->iName, info); |
|
1168 } |
|
1169 } |
|
1170 CleanupStack::PopAndDestroy(fileList); |
|
1171 fileList = NULL; |
|
1172 } |
|
1173 CleanupStack::PopAndDestroy(2, &fileMap); // fileMap, fs |
|
1174 } |
|
1175 else |
|
1176 { |
|
1177 // No refreshing possible for open files |
|
1178 } |
|
1179 } |
|
1180 else if (iCurrentList == EListFeatureReg) |
|
1181 { |
|
1182 // Can't link directly against featreg.dll because it doesn't exist on generic 9.1 |
|
1183 RLibrary featLib; |
|
1184 TInt err = featLib.Load(_L("featreg.dll")); |
|
1185 if (err) return; // No feature registry, no features! |
|
1186 |
|
1187 #ifdef __WINS__ |
|
1188 #define KQueryOrdinal 9 |
|
1189 #else |
|
1190 #define KQueryOrdinal 4 |
|
1191 #endif |
|
1192 |
|
1193 typedef TInt (*QueryFn)(TUid, TUint32&); |
|
1194 QueryFn Query = (QueryFn)featLib.Lookup(KQueryOrdinal); |
|
1195 |
|
1196 if (aIndex == -1) |
|
1197 { |
|
1198 RArray<TUid> features; |
|
1199 CleanupClosePushL(features); |
|
1200 gPlugin->GetFeatureUidsL(features); |
|
1201 |
|
1202 for (TInt i = 0; i < features.Count(); i++) |
|
1203 { |
|
1204 SFeature* info = new(ELeave) SFeature; |
|
1205 CleanupStack::PushL(info); |
|
1206 info->iFeature = features[i].iUid; |
|
1207 info->iErr = Query(features[i], info->iInfo); |
|
1208 model.NewKernDataL(iCurrentList, reinterpret_cast<TObjectKernelInfo*>(info)); |
|
1209 CleanupStack::Pop(info); |
|
1210 } |
|
1211 CleanupStack::PopAndDestroy(&features); |
|
1212 } |
|
1213 else |
|
1214 { |
|
1215 SFeature* info = reinterpret_cast<SFeature*>(data->iInfo); |
|
1216 info->iErr = Query(TUid::Uid(info->iFeature), info->iInfo); |
|
1217 } |
|
1218 featLib.Close(); |
|
1219 } |
|
1220 else |
|
1221 { |
|
1222 // Generic code that works for all first-class Kernel objects (ie processes, threads, chunks. Despite appearances, code segs are not first-class kernel objects). |
|
1223 |
|
1224 TInt sizeofObjectBuf = 0; |
|
1225 switch(iCurrentList) |
|
1226 { |
|
1227 case EListProcess: |
|
1228 sizeofObjectBuf = sizeof(TProcessKernelInfo); break; |
|
1229 case EListThread: |
|
1230 sizeofObjectBuf = sizeof(TThreadKernelInfo); break; |
|
1231 case EListChunk: |
|
1232 sizeofObjectBuf = sizeof(TChunkKernelInfo); break; |
|
1233 case EListServer: |
|
1234 sizeofObjectBuf = sizeof(TServerKernelInfo); break; |
|
1235 case EListMessageQueue: |
|
1236 sizeofObjectBuf = sizeof(TMsgQueueKernelInfo); break; |
|
1237 case EListMutex: |
|
1238 sizeofObjectBuf = sizeof(TMutexKernelInfo); break; |
|
1239 case EListSemaphore: |
|
1240 sizeofObjectBuf = sizeof(TSemaphoreKernelInfo); break; |
|
1241 case EListTimer: |
|
1242 sizeofObjectBuf = sizeof(TTimerKernelInfo); break; |
|
1243 default: |
|
1244 User::Panic(_L("QR3 Missing type"), iCurrentList); |
|
1245 } |
|
1246 |
|
1247 if (aIndex == -1) |
|
1248 { |
|
1249 // Be paranoid about releasing the mutexes, to avoid the risk of deadlocking. Only likely if we were looking through the chunk container AND needed to grow our chunk in NewKernDataL, but err on the side of caution |
|
1250 //mem.AcquireContainerMutex(type); |
|
1251 TUint count; |
|
1252 mem.GetContainerCount(type, count); |
|
1253 //mem.ReleaseContainerMutex(type); |
|
1254 for (TUint i = 0; i < count; i++) |
|
1255 { |
|
1256 info = (TObjectKernelInfo*)User::AllocZL(sizeofObjectBuf); |
|
1257 buf.Set((TUint8*)info, sizeofObjectBuf, sizeofObjectBuf); |
|
1258 |
|
1259 CleanupStack::PushL(info); |
|
1260 // Don't need to grab the lock any more |
|
1261 //mem.AcquireContainerMutex(type); |
|
1262 TInt err = mem.GetObjectInfo(type, i, buf); |
|
1263 //mem.ReleaseContainerMutex(type); |
|
1264 if (err == KErrNone) |
|
1265 { |
|
1266 model.NewKernDataL(iCurrentList, info); |
|
1267 CleanupStack::Pop(info); |
|
1268 } |
|
1269 else |
|
1270 { |
|
1271 CleanupStack::PopAndDestroy(info); |
|
1272 } |
|
1273 } |
|
1274 } |
|
1275 else |
|
1276 { |
|
1277 buf.Set((TUint8*)data->iInfo, sizeofObjectBuf, sizeofObjectBuf); |
|
1278 mem.GetObjectInfo(type, data->iInfo->iAddressOfKernelObject, buf); // Nothing required on error |
|
1279 } |
|
1280 } |
|
1281 |
|
1282 if (aIndex != -1) |
|
1283 { |
|
1284 data->FormatL(data->iInfo, iTempBuf1, iTempBuf2); |
|
1285 model.DataUpdatedL(aIndex); |
|
1286 CleanupStack::PopAndDestroy(data); |
|
1287 } |
|
1288 model.Sort(); // We can't do this in NewKernDataL because the things we sort on aren't setup until FormatL |
|
1289 model.ModelEndUpdateL(); |
|
1290 |
|
1291 if (iInfoChangedCallback.iFunction != NULL && (aIndex == -1 || data == iCallbackData)) |
|
1292 { |
|
1293 iInfoChangedCallback.CallBack(); |
|
1294 } |
|
1295 } |
|
1296 |
|
1297 void CKernListBoxModel::Sort(TLinearOrder<CKernListBoxData> aOrder) |
|
1298 { |
|
1299 iSort = aOrder; |
|
1300 Sort(); |
|
1301 } |
|
1302 |
|
1303 void CKernListBoxModel::Sort() |
|
1304 { |
|
1305 if (iSort) |
|
1306 { |
|
1307 User::QuickSort(Count(), *this, *this); |
|
1308 } |
|
1309 } |
|
1310 |
|
1311 void CKernListBoxModel::SetInfoChangedCallback(TInt aIndex, const TCallBack& aCallback) |
|
1312 { |
|
1313 iInfoChangedCallback = aCallback; |
|
1314 if (aCallback.iFunction) |
|
1315 { |
|
1316 iCallbackData = iItemData[aIndex]; |
|
1317 iCallbackData->Open(); |
|
1318 } |
|
1319 else |
|
1320 { |
|
1321 iCallbackData->Close(); |
|
1322 iCallbackData = NULL; |
|
1323 } |
|
1324 } |
|
1325 |
|
1326 void CKernListBoxData::Open() |
|
1327 { |
|
1328 iRefCount++; |
|
1329 } |
|
1330 |
|
1331 void CKernListBoxData::Close() |
|
1332 { |
|
1333 iRefCount--; |
|
1334 if (iRefCount == 0) |
|
1335 delete this; |
|
1336 } |
|
1337 |
|
1338 void CKernListBoxData::SetDelegate(MKernListBoxDataDelegate* aDelegate) |
|
1339 { |
|
1340 iDelegate = aDelegate; |
|
1341 } |
|
1342 |
|
1343 MKernListBoxDataDelegate* CKernListBoxData::Delegate() |
|
1344 { |
|
1345 return iDelegate; |
|
1346 } |
|
1347 |
|
1348 const MKernListBoxDataDelegate* CKernListBoxData::Delegate() const |
|
1349 { |
|
1350 return iDelegate; |
|
1351 } |
|
1352 |
|
1353 TInt CKernListBoxData::ItemId() const |
|
1354 { |
|
1355 return iItemId; |
|
1356 } |
|
1357 |
|
1358 void CKernListBoxData::SetItemId(TInt aItemId) |
|
1359 { |
|
1360 iItemId = aItemId; |
|
1361 } |
|
1362 |
|
1363 void CKernListBoxData::ConstructL() |
|
1364 { |
|
1365 } |
|
1366 |
|
1367 CKernListBoxModel& CKernListBoxData::Model() |
|
1368 { |
|
1369 return *iModel; |
|
1370 } |