|
1 // Copyright (c) 1999-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 // f32test\loader\t_ldrtst2.cpp |
|
15 // |
|
16 // |
|
17 |
|
18 #include "t_ldrtst.h" |
|
19 |
|
20 extern TInt GetModuleFlags(TInt); |
|
21 |
|
22 inline TBool AlwaysLoaded(TInt aModule) |
|
23 { |
|
24 #ifdef __EPOC32__ |
|
25 TUint32 f=GetModuleFlags(aModule); |
|
26 return ( (f&(KModuleFlagExe|KModuleFlagDataInTree|KModuleFlagXIP)) == (TUint32)KModuleFlagXIP ); |
|
27 #else |
|
28 TUint32 f=GetModuleFlags(aModule); |
|
29 return ( (f&(KModuleFlagExe|KModuleFlagDataInTree)) == 0 ); |
|
30 #endif |
|
31 } |
|
32 |
|
33 TInt Order(const SModuleInstance& m1, const SModuleInstance& m2) |
|
34 { |
|
35 return TInt(m1.iCodeSeg)-TInt(m2.iCodeSeg); |
|
36 } |
|
37 |
|
38 CGlobalModuleList::CGlobalModuleList() |
|
39 : iModules(KNumModules) |
|
40 { |
|
41 } |
|
42 |
|
43 CGlobalModuleList::~CGlobalModuleList() |
|
44 { |
|
45 iModules.Close(); |
|
46 User::Free(iModuleAlloc); |
|
47 TInt i; |
|
48 for (i=0; i<KNumModules; ++i) |
|
49 { |
|
50 delete iPPInfo[i]; |
|
51 } |
|
52 } |
|
53 |
|
54 void CGlobalModuleList::Init() |
|
55 { |
|
56 TBool proc_sym=(iMemModelAtt & (EMemModelAttrSameVA|EMemModelAttrSupportFixed))==EMemModelAttrSameVA; |
|
57 TInt i; |
|
58 for (i=0; i<KNumModules; ++i) |
|
59 { |
|
60 TUint32 f=GetModuleFlags(i); |
|
61 if (f&KModuleFlagExe) |
|
62 { |
|
63 ++iNumExes; |
|
64 if (!proc_sym && (f&KModuleFlagFixed)) |
|
65 ++iFixedExes; |
|
66 } |
|
67 } |
|
68 iMaxModules=(1+iFixedExes)*(KNumModules-iNumExes)+iNumExes; |
|
69 test.Printf(_L("iNumExes=%d iFixedExes=%d iMaxModules=%d\n"),iNumExes,iFixedExes,iMaxModules); |
|
70 SModuleInstance* mi=(SModuleInstance*)User::Alloc(iMaxModules*sizeof(SModuleInstance)); |
|
71 test(mi!=NULL); |
|
72 iFreeModules=mi; |
|
73 iModuleAlloc=mi; |
|
74 SModuleInstance* miE=mi+iMaxModules; |
|
75 for (; mi<miE; ++mi) |
|
76 { |
|
77 SModuleInstance* miN=mi+1; |
|
78 mi->iCodeSeg=(miN<miE)?miN:NULL; |
|
79 } |
|
80 for (i=0; i<KNumModules; ++i) |
|
81 { |
|
82 TUint32 f=GetModuleFlags(i); |
|
83 if (f&KModuleFlagExe) |
|
84 { |
|
85 CPerProcessInfo* p=CPerProcessInfo::New(i,*this); |
|
86 iPPInfo[i]=p; |
|
87 } |
|
88 } |
|
89 } |
|
90 |
|
91 CGlobalModuleList* CGlobalModuleList::New(const LoaderTest& a) |
|
92 { |
|
93 CGlobalModuleList* p=new CGlobalModuleList; |
|
94 test(p!=NULL); |
|
95 test.Printf(_L("CGlobalModuleList at %08x\n"),p); |
|
96 p->iDev=a.iDev; |
|
97 p->iMemModelAtt=a.iMemModelAtt; |
|
98 p->Init(); |
|
99 return p; |
|
100 } |
|
101 |
|
102 void CGlobalModuleList::Free(SModuleInstance* a) |
|
103 { |
|
104 a->iCodeSeg=iFreeModules; |
|
105 iFreeModules=a; |
|
106 } |
|
107 |
|
108 SModuleInstance* CGlobalModuleList::GetMI() |
|
109 { |
|
110 SModuleInstance* p=iFreeModules; |
|
111 test(p!=NULL); |
|
112 iFreeModules=(SModuleInstance*)p->iCodeSeg; |
|
113 return p; |
|
114 } |
|
115 |
|
116 TAny* CGlobalModuleList::CodeSegFromHandle(TModuleHandle aModHandle) |
|
117 { |
|
118 return iDev.ModuleCodeSeg(aModHandle); |
|
119 } |
|
120 |
|
121 void CGlobalModuleList::Close(SModuleInstance* a) |
|
122 { |
|
123 test.Printf(_L("Module %d@%08x Close(%d)\n"),a->iModNum,a->iCodeSeg,a->iAccessCount); |
|
124 if (!--a->iAccessCount) |
|
125 { |
|
126 TCodeSegCreateInfo codeSeg; |
|
127 TInt r=iDev.GetCodeSegInfo(a->iCodeSeg, codeSeg); |
|
128 test(r==KErrArgument); |
|
129 r=iModules.FindInOrder(a, Order); |
|
130 test(r>=0); |
|
131 iModules.Remove(r); |
|
132 Free(a); |
|
133 } |
|
134 } |
|
135 |
|
136 |
|
137 void CGlobalModuleList::CheckAll() |
|
138 { |
|
139 TInt i; |
|
140 for (i=0; i<KNumModules; ++i) |
|
141 { |
|
142 if (iPPInfo[i]) |
|
143 iPPInfo[i]->Check(); |
|
144 } |
|
145 } |
|
146 |
|
147 TInt CGlobalModuleList::Load(TInt aExeNum, TInt aDllNum) |
|
148 { |
|
149 return iPPInfo[aExeNum]->Load(aDllNum); |
|
150 } |
|
151 |
|
152 TInt CGlobalModuleList::CloseHandle(TInt aExeNum, TInt aDllNum) |
|
153 { |
|
154 CPerProcessInfo* p=iPPInfo[aExeNum]; |
|
155 TInt i; |
|
156 for (i=0; i<KMaxHandles && p->iModuleNum[i]!=aDllNum; ++i) {} |
|
157 if (i==KMaxHandles) |
|
158 return KErrNotFound; |
|
159 return p->CloseHandle(i); |
|
160 } |
|
161 |
|
162 CPerProcessInfo::CPerProcessInfo() |
|
163 { |
|
164 Mem::Fill(iModuleNum, sizeof(iModuleNum), 0xff); |
|
165 } |
|
166 |
|
167 CPerProcessInfo::~CPerProcessInfo() |
|
168 { |
|
169 if (iSession.Handle()) |
|
170 { |
|
171 iSession.Exit(); |
|
172 iSession.Close(); |
|
173 User::WaitForRequest(iStatus); |
|
174 test(iProcess.ExitType()==EExitKill); |
|
175 test(iProcess.ExitReason()==KErrNone); |
|
176 } |
|
177 iProcess.Close(); |
|
178 } |
|
179 |
|
180 CPerProcessInfo* CPerProcessInfo::New(TInt aExeNum, CGlobalModuleList& aG) |
|
181 { |
|
182 CPerProcessInfo* p=new CPerProcessInfo; |
|
183 test(p!=NULL); |
|
184 test.Printf(_L("CPerProcessInfo for %d at %08x\n"),aExeNum,p); |
|
185 p->iExeNum=aExeNum; |
|
186 p->iDev=aG.iDev; |
|
187 p->iGlobalList=&aG; |
|
188 TInt r = p->Init(); |
|
189 if (r==KErrNone) |
|
190 return p; |
|
191 delete p; |
|
192 return NULL; |
|
193 } |
|
194 |
|
195 TInt CPerProcessInfo::Init() |
|
196 { |
|
197 TUint32 tt; |
|
198 TInt r=LoadExe(iExeNum, 0, iProcess, tt); |
|
199 test.Printf(_L("LoadExe(%d)->%d\n"),iExeNum,r); |
|
200 #ifdef __EPOC32__ |
|
201 test(r==KErrNone); |
|
202 test.Printf(_L("BENCHMARK: LoadExe(%d)->%dms\n"),iExeNum,tt); |
|
203 #else |
|
204 test(r==KErrNone || r==KErrNotSupported); |
|
205 if (r!=KErrNone) |
|
206 return r; |
|
207 #endif |
|
208 iProcess.Logon(iStatus); |
|
209 test(iStatus==KRequestPending); |
|
210 r=iSession.Connect(iExeNum); |
|
211 test.Printf(_L("Connect(%d)->%d\n"),iExeNum,r); |
|
212 test(r==KErrNone); |
|
213 TModuleList exe_info; |
|
214 r=iSession.GetExeDepList(exe_info.iInfo); |
|
215 exe_info.SetCount(); |
|
216 test.Printf(_L("GetExeDepList(%d)->%d count %d\n"),iExeNum,r,exe_info.iCount); |
|
217 test(r==KErrNone); |
|
218 r=AddModules(iExeNum, NULL, &exe_info); |
|
219 test.Printf(_L("AddModules->%d\n"),r); |
|
220 test(r==KErrNone); |
|
221 return KErrNone; |
|
222 } |
|
223 |
|
224 void CPerProcessInfo::GetModuleSet(TModuleSet& aSet) |
|
225 { |
|
226 TInt m; |
|
227 for (m=0; m<KNumModules; ++m) |
|
228 { |
|
229 if (iHandleCount[m]==0 && m!=iExeNum) |
|
230 continue; |
|
231 aSet.Add(m); |
|
232 const TInt* deps=ModuleDependencies[m]; |
|
233 TInt ndeps=*deps++; |
|
234 TInt i; |
|
235 for (i=0; i<ndeps; ++i) |
|
236 { |
|
237 TInt dm=*deps++; |
|
238 #ifndef __EPOC32__ |
|
239 // Emulator doesn't register subtrees without data |
|
240 TInt f = GetModuleFlags(dm); |
|
241 if (f & KModuleFlagDataInTree) |
|
242 #endif |
|
243 aSet.Add(dm); |
|
244 } |
|
245 } |
|
246 } |
|
247 |
|
248 void CPerProcessInfo::Check() |
|
249 { |
|
250 test.Printf(_L("%d:Check\n"),iExeNum); |
|
251 TBool code_prot=iGlobalList->iMemModelAtt&EMemModelAttrRamCodeProt; |
|
252 TBool data_prot=iGlobalList->iMemModelAtt&EMemModelAttrProcessProt; |
|
253 TInt mmtype=iGlobalList->iMemModelAtt&EMemModelTypeMask; |
|
254 TModuleSet set; |
|
255 GetModuleSet(set); |
|
256 TInt m; |
|
257 for (m=0; m<KNumModules; ++m) |
|
258 { |
|
259 TUint32 f=GetModuleFlags(m); |
|
260 if (set.Present(m)) |
|
261 { |
|
262 test.Printf(_L("%d "),m); |
|
263 SModuleInstance* pM=iModules[m]; |
|
264 test(pM!=NULL); |
|
265 test(iSession.CheckReadable(pM->iEntryPointAddress)==KErrNone); |
|
266 if (f&KModuleFlagData) |
|
267 test(iSession.CheckReadable(pM->iData)==KErrNone); |
|
268 } |
|
269 else |
|
270 { |
|
271 SModuleInstance* pM=iModules[m]; |
|
272 test(pM==NULL); |
|
273 } |
|
274 } |
|
275 TInt ix; |
|
276 TInt c=iGlobalList->iModules.Count(); |
|
277 test.Printf(_L("\n%d:CheckNP\n"),iExeNum); |
|
278 for (ix=0; ix<c; ++ix) |
|
279 { |
|
280 const SModuleInstance* pM=iGlobalList->iModules[ix]; |
|
281 if (set.Present(pM->iModNum)) |
|
282 continue; |
|
283 test.Printf(_L("%d "),pM->iModNum); |
|
284 TUint32 f=GetModuleFlags(pM->iModNum); |
|
285 if (!(f&KModuleFlagXIP) && code_prot) |
|
286 { |
|
287 if(mmtype==EMemModelTypeFlexible && (f&KModuleFlagExe)) |
|
288 { |
|
289 // don't test EXEs on FlexibleMM because they don't live at unique addresses |
|
290 } |
|
291 else |
|
292 { |
|
293 // check code not loaded into this porcess.... |
|
294 test(iSession.CheckReadable(pM->iEntryPointAddress)==KErrGeneral); |
|
295 } |
|
296 } |
|
297 TBool check_data=(f&(KModuleFlagData|KModuleFlagExe))==(TUint32)KModuleFlagData; |
|
298 if (check_data && mmtype==EMemModelTypeMoving) |
|
299 { |
|
300 if (f&KModuleFlagXIP) |
|
301 { |
|
302 const TInt* exeinfo=ModuleExeInfo[pM->iModNum]; |
|
303 TInt attp=exeinfo[0]; |
|
304 if (attp>=0 && (GetModuleFlags(attp)&KModuleFlagFixed)) |
|
305 check_data=EFalse; |
|
306 } |
|
307 } |
|
308 if (check_data && data_prot) |
|
309 test(iSession.CheckReadable(pM->iData)==KErrGeneral); |
|
310 } |
|
311 TInt h; |
|
312 for (h=0; h<KMaxHandles; ++h) |
|
313 { |
|
314 m=iModuleNum[h]; |
|
315 if (m<0) |
|
316 continue; |
|
317 test(set.Present(m)); |
|
318 TInt y=++iGlobalList->iParam; |
|
319 TInt r=iSession.CallRBlkI(h,y); |
|
320 r-=y; |
|
321 r/=INC_BLOCK_SZ; |
|
322 test.Printf(_L("DLL %d RBlkI->%d\n"),m,r); |
|
323 y=ModuleRBlkIParams[m][1]+ModuleRBlkIParams[m][0]*DLLNUMOFFSET; |
|
324 test(r==y); |
|
325 } |
|
326 } |
|
327 |
|
328 void CPerProcessInfo::Unlink(const SDllInfo& a, TModuleList& aList) |
|
329 { |
|
330 test.Printf(_L("%d:Unlink %d %08x\n"),iExeNum,a.iDllNum,a.iModuleHandle); |
|
331 test(iHandleCount[a.iDllNum]==0); |
|
332 TBool code_prot=iGlobalList->iMemModelAtt&EMemModelAttrRamCodeProt; |
|
333 TBool data_prot=iGlobalList->iMemModelAtt&EMemModelAttrProcessProt; |
|
334 TInt mmtype=iGlobalList->iMemModelAtt&EMemModelTypeMask; |
|
335 TModuleSet set; |
|
336 GetModuleSet(set); |
|
337 set.Display(_L("set: ")); |
|
338 TInt m; |
|
339 for (m=0; m<KNumModules; ++m) |
|
340 { |
|
341 if (set.Present(m)) |
|
342 continue; |
|
343 SModuleInstance* pM=iModules[m]; |
|
344 if (!pM) |
|
345 continue; |
|
346 iModules[m]=NULL; |
|
347 TUint32 f=GetModuleFlags(m); |
|
348 SDllInfo info; |
|
349 info.iDllNum=m; |
|
350 info.iEntryPointAddress=pM->iEntryPointAddress; |
|
351 info.iModuleHandle=pM->iModuleHandle; |
|
352 aList.Add(info); |
|
353 test(pM->iModNum==m); |
|
354 if (!(f&KModuleFlagXIP) && code_prot) |
|
355 test(iSession.CheckReadable(pM->iEntryPointAddress)==KErrGeneral); |
|
356 TBool check_data=f&KModuleFlagData; |
|
357 if (check_data && mmtype==EMemModelTypeMoving) |
|
358 { |
|
359 if (f&KModuleFlagXIP) |
|
360 { |
|
361 const TInt* exeinfo=ModuleExeInfo[pM->iModNum]; |
|
362 TInt attp=exeinfo[0]; |
|
363 if (attp>=0 && (GetModuleFlags(attp)&KModuleFlagFixed)) |
|
364 check_data=EFalse; |
|
365 } |
|
366 } |
|
367 if (check_data && data_prot) |
|
368 test(iSession.CheckReadable(pM->iData)==KErrGeneral); |
|
369 iGlobalList->Close(pM); |
|
370 } |
|
371 } |
|
372 |
|
373 TInt CPerProcessInfo::CloseHandle(TInt aHandle) |
|
374 { |
|
375 TInt m=iModuleNum[aHandle]; |
|
376 test(m>=0); |
|
377 iModuleNum[aHandle]=-1; |
|
378 SModuleInstance* pM=iModules[m]; |
|
379 test(pM!=NULL); |
|
380 SDllInfo dll_info; |
|
381 dll_info.iDllNum=m; |
|
382 dll_info.iEntryPointAddress=pM->iEntryPointAddress; |
|
383 dll_info.iModuleHandle=pM->iModuleHandle; |
|
384 TModuleList d_list; |
|
385 TInt r=iSession.CloseDll(aHandle); |
|
386 test(r==KErrNone); |
|
387 r=iSession.GetCDList(d_list.iInfo); |
|
388 test(r==KErrNone); |
|
389 d_list.SetCount(); |
|
390 if (--iHandleCount[m]) |
|
391 { |
|
392 test(d_list.iCount==0); |
|
393 return KErrNone; |
|
394 } |
|
395 TModuleList xd_list; |
|
396 if (!AlwaysLoaded(m)) |
|
397 Unlink(dll_info, xd_list); |
|
398 TInt i; |
|
399 TInt dcount=0; |
|
400 for (i=0; i<xd_list.iCount; ++i) |
|
401 { |
|
402 TInt mn=xd_list.iInfo[i].iDllNum; |
|
403 TUint32 f=GetModuleFlags(mn); |
|
404 if (f&KModuleFlagData) |
|
405 { |
|
406 ++dcount; |
|
407 test(d_list.IsPresent(mn)); |
|
408 } |
|
409 } |
|
410 d_list.Display(_L("d_list: ")); |
|
411 xd_list.Display(_L("xd_list: ")); |
|
412 test(dcount==d_list.iCount); |
|
413 return KErrNone; |
|
414 } |
|
415 |
|
416 TInt CPerProcessInfo::Load(TInt aDllNum) |
|
417 { |
|
418 TModuleList init_list; |
|
419 TModuleList c_list; |
|
420 TInt h=iSession.LoadDll(aDllNum, init_list.iInfo); |
|
421 init_list.SetCount(); |
|
422 test.Printf(_L("%d:Load(%d)->%d Icount %d\n"),iExeNum,aDllNum,h,init_list.iCount); |
|
423 if (h<0) |
|
424 { |
|
425 return h; |
|
426 } |
|
427 test(iSession.GetCDList(c_list.iInfo)==KErrNone); |
|
428 c_list.SetCount(); |
|
429 iModuleNum[h]=aDllNum; |
|
430 return AddModules(aDllNum, &c_list, &init_list); |
|
431 } |
|
432 |
|
433 TInt CPerProcessInfo::AddModules(TInt aDllNum, TModuleList* aCList, TModuleList* aIList) |
|
434 { |
|
435 TInt r=0; |
|
436 if (++iHandleCount[aDllNum]>1) |
|
437 { |
|
438 if (aCList) |
|
439 test(aCList->iCount==0); |
|
440 return KErrNone; |
|
441 } |
|
442 TModuleSet set; |
|
443 if (!iModules[aDllNum] && !AlwaysLoaded(aDllNum)) |
|
444 set.Add(aDllNum); |
|
445 const TInt* deps=ModuleDependencies[aDllNum]; |
|
446 TInt ndeps=*deps++; |
|
447 TInt i; |
|
448 TInt ccount=0; |
|
449 for (i=0; i<ndeps; ++i) |
|
450 { |
|
451 TInt dm=*deps++; |
|
452 if (!iModules[dm] && !AlwaysLoaded(dm)) |
|
453 { |
|
454 set.Add(dm); |
|
455 if (GetModuleFlags(dm)&KModuleFlagData) |
|
456 ++ccount; |
|
457 } |
|
458 } |
|
459 if (aCList) |
|
460 test(ccount==aCList->iCount); |
|
461 for (i=0; i<KNumModules; ++i) |
|
462 { |
|
463 if (!set.Present(i)) |
|
464 continue; |
|
465 SModuleInstance mi; |
|
466 mi.iAccessCount=1; |
|
467 mi.iModNum=i; |
|
468 if (GetModuleFlags(i)&KModuleFlagData) |
|
469 { |
|
470 if (aCList) |
|
471 test(aCList->Find(i)>=0); |
|
472 } |
|
473 TInt j=aIList->Find(i); |
|
474 test(j>=0); |
|
475 mi.iEntryPointAddress=aIList->iInfo[j].iEntryPointAddress; |
|
476 mi.iModuleHandle=aIList->iInfo[j].iModuleHandle; |
|
477 mi.iCodeSeg=iGlobalList->CodeSegFromHandle(mi.iModuleHandle); |
|
478 test(mi.iCodeSeg!=NULL); |
|
479 if (GetModuleFlags(i)&KModuleFlagData) |
|
480 { |
|
481 TCodeSegCreateInfo cs_info; |
|
482 r=iDev.GetCodeSegInfo(mi.iCodeSeg, cs_info); |
|
483 test(r==KErrNone); |
|
484 mi.iData=cs_info.iDataRunAddress; |
|
485 } |
|
486 else |
|
487 { |
|
488 mi.iData=0; |
|
489 } |
|
490 |
|
491 r=iGlobalList->iModules.FindInOrder(&mi, Order); |
|
492 if (r>=0) |
|
493 { |
|
494 test.Printf(_L("Module %d@%08x already exists\n"),mi.iModNum,mi.iCodeSeg); |
|
495 SModuleInstance& mi0=*iGlobalList->iModules[r]; |
|
496 ++mi0.iAccessCount; |
|
497 test(mi.iEntryPointAddress==mi0.iEntryPointAddress); |
|
498 test(mi.iModuleHandle==mi0.iModuleHandle); |
|
499 test(mi.iData==mi0.iData); |
|
500 test(mi.iModNum==mi0.iModNum); |
|
501 iModules[i]=&mi0; |
|
502 } |
|
503 else |
|
504 { |
|
505 test.Printf(_L("Module %d@%08x new\n"),mi.iModNum,mi.iCodeSeg); |
|
506 SModuleInstance* pM=iGlobalList->GetMI(); |
|
507 test(pM!=NULL); |
|
508 *pM=mi; |
|
509 iModules[i]=pM; |
|
510 r=iGlobalList->iModules.InsertInOrder(pM, Order); |
|
511 test(r==KErrNone); |
|
512 } |
|
513 } |
|
514 return KErrNone; |
|
515 } |
|
516 |
|
517 void LoaderTest::TestMultipleLoads() |
|
518 { |
|
519 CGlobalModuleList* p=CGlobalModuleList::New(*this); |
|
520 p->CheckAll(); |
|
521 |
|
522 #ifdef __WINS__ |
|
523 const TInt* multiLoad[] = {TC_MultLoad,0}; |
|
524 #else |
|
525 const TInt* multiLoad[] = {TC_MultLoad,TC_MultLoadTargetOnly,0}; |
|
526 #endif |
|
527 const TInt** multiLoadLists = multiLoad; |
|
528 const TInt* tests; |
|
529 while((tests=*multiLoadLists++)!=0) |
|
530 { |
|
531 TInt ntests=*tests++; |
|
532 while(ntests>=4) |
|
533 { |
|
534 ntests-=4; |
|
535 TInt exe1=*tests++; |
|
536 TInt dll1=*tests++; |
|
537 TInt exe2=*tests++; |
|
538 TInt dll2=*tests++; |
|
539 TUint32 xf1=GetModuleFlags(exe1); |
|
540 TUint32 xf2=GetModuleFlags(exe2); |
|
541 if (xf1&KModuleFlagExe) |
|
542 { |
|
543 TInt r=p->Load(exe1, dll1); |
|
544 test.Printf(_L("%d:Load %d->%d"),exe1,dll1,r); |
|
545 p->CheckAll(); |
|
546 } |
|
547 if (xf2&KModuleFlagExe) |
|
548 { |
|
549 TInt r=p->CloseHandle(exe2, dll2); |
|
550 test.Printf(_L("%d:Close %d->%d"),exe2,dll2,r); |
|
551 p->CheckAll(); |
|
552 } |
|
553 } |
|
554 } |
|
555 |
|
556 delete p; |
|
557 } |
|
558 |