Trying to figure out how to implement my WINC like compatibility layer. Going the emulation way is probably not so smart. We should not use the kernel but rather hook native functions in the Exec calls.
// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of the License "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
// f32test\server\t_rcount.cpp
//
//
#include <f32file.h>
#include <e32test.h>
#include "../server/t_server.h"
GLDEF_D RTest test(_L("T_RCOUNT"));
const TInt KHeapSize=0x2000;
LOCAL_C void Test1()
//
// Test resource counting success
//
{
test.Start(_L("Test resource count success"));
RFs TheFs;
TheFs.Connect();
RFile file;
TheFs.ResourceCountMarkStart();
TInt count=TheFs.ResourceCount();
test(count==0);
TFileName name=_L("Z:\\Test\\T_FILE.CPP");
name[0] = gExeFileName[0];
test.Printf(_L("%S\n"),&name);
TInt r=file.Open(TheFs,name,EFileRead);
test(r==KErrNone);
count=TheFs.ResourceCount();
test(count==1);
file.Close();
count=TheFs.ResourceCount();
test(count==0);
TheFs.ResourceCountMarkEnd();
TheFs.Close();
}
LOCAL_C TInt TestPanic(TAny*)
//
// The Test thread
//
{
User::SetJustInTime(EFalse);
RFs fs;
TInt r=fs.Connect();
test(r==KErrNone);
RFile file;
fs.ResourceCountMarkStart();
TFileName name=_L("Z:\\Test\\T_FILE.CPP");
name[0] = gExeFileName[0];
r=file.Open(fs,name,EFileRead);
test(r==KErrNone);
TInt count=fs.ResourceCount();
test(count==1);
fs.ResourceCountMarkEnd(); // MarkEnd without close
fs.Close();
return KErrNone;
}
LOCAL_C void Test2()
//
// Test resource count failure
//
{
test.Next(_L("Test resource count failure"));
TRequestStatus stat;
RThread t;
TInt r=t.Create(_L("TestPanicThread"),TestPanic,KDefaultStackSize,KHeapSize,KHeapSize,NULL);
test(r==KErrNone);
t.Logon(stat);
t.Resume();
User::WaitForRequest(stat);
test(t.ExitReason()==CSession2::ESesFoundResCountHeaven);
test(t.ExitType()==EExitPanic);
CLOSE_AND_WAIT(t);
}
_LIT(KDirName1, "c:\\f32-tst");
_LIT(KFileName1, "c:\\crash001.txt");
_LIT(KFileName2, "c:\\crash002.txt");
LOCAL_C TInt SendBadHandle1(TAny *)
//
// Thread is panicked when server leaves when DoFsSubCloseL() calls CObjectIx::AtL().
// Avoid case where thread is panicked by CObjectIx::Remove() because
// ! (i<iHighWaterMark) closing the first file removes all of the CObjects.
//
{
RFs fs;
test(fs.Connect() == KErrNone);
RFile f1;
test(f1.Replace(fs, KFileName1, EFileWrite) == KErrNone);
RFile fc(f1);
f1.Close();
fc.Close(); // file server panics thread here
test(EFalse);
fs.Close();
return KErrNone; // shouldn't reach here
}
LOCAL_C TInt SendBadHandle2(TAny *)
//
// Thread is panicked when server leaves when DoFsSubClose() calls CObjectIx::AtL().
// Avoid case where thread is panicked by CObjectIx() because ! pR->obj, with handle
// having been already removed.
//
{
RFs fs;
test(fs.Connect() == KErrNone);
RFile f1;
test(f1.Replace(fs, KFileName1, EFileWrite) == KErrNone);
RFile f2;
test(f2.Replace(fs, KFileName2, EFileWrite) == KErrNone);
RFile fc(f1);
f1.Close();
fc.Close(); // file server panics thread here
test(EFalse);
fs.Close();
return KErrNone; // shouldn't reach here
}
LOCAL_C TInt SendBadHandle3(TAny*)
//
// Setup a bad RFile handle then try to write to the file,
// the thread should get paniced by the file server
//
{
RFs f;
TInt r = f.Connect();
test(r==KErrNone);
RFile a;
r=a.Replace(f,KFileName1,EFileWrite);
test(r==KErrNone);
RFile b(a);
a.Close();
r=b.Write(_L8("testing testing"));
//thread should get paniced here so should not reach this
test(EFalse);
f.Close();
return KErrNone;
}
LOCAL_C TInt SendBadHandle4(TAny*)
//
// Setup a bad RDir handle then try to read the Directory,
// the thread should get panniced by the server
//
{
RFs f;
TInt r = f.Connect();
test(r==KErrNone);
RDir a;
r=a.Open(f,KDirName1,KEntryAttNormal);
test(r==KErrNone);
RDir b(a);
a.Close();
TEntryArray dummyarray;
r=b.Read(dummyarray);
//thread should get paniced here so should not reach this
test(EFalse);
f.Close();
return KErrNone;
}
LOCAL_C TInt SendBadHandle5(TAny*)
//
// Setup a bad RFormat handle then try to call next on the Format object,
// the thread should get panniced by the server
//
{
#if defined(__EPOC32__)
_LIT(KDrive1, "C:\\");
#else
_LIT(KDrive1, "X:\\");
#endif
RFs f;
TInt r = f.Connect();
test(r==KErrNone);
RFormat a;
TInt count;
r=a.Open(f,KDrive1,EQuickFormat,count);
test(r==KErrNone);
RFormat b(a);
a.Close();
r=b.Next(count);
//thread should get paniced here so should not reach this
test(EFalse);
f.Close();
return KErrNone;
}
LOCAL_C TInt SendBadHandle6(TAny*)
//
// Setup a bad RRawDisk handle then try to call read on the raw disk object,
// the thread should get panniced by the server
//
{
#if defined(__EPOC32__)
const TInt KDrive1 = EDriveC;
#else
const TInt KDrive1 = EDriveX;
#endif
RFs f;
TInt r = f.Connect();
test(r==KErrNone);
RRawDisk a;
r=a.Open(f,KDrive1);
test(r==KErrNone);
RRawDisk b(a);
a.Close();
TBuf8<19> buffer;
r=b.Read(0,buffer);
//thread should get paniced here so should not reach this
test(EFalse);
f.Close();
return KErrNone;
}
LOCAL_C void Test3()
//
// Test how the file server copes with bad handles
//
{
test.Start(_L("RunTests()"));
TRequestStatus rs;
RThread t1;
User::SetJustInTime(EFalse);
test(t1.Create(_L("Handle1Test"), SendBadHandle1, KDefaultStackSize, KHeapSize, KHeapSize, NULL) == KErrNone);
t1.Logon(rs);
t1.Resume();
User::WaitForRequest(rs);
User::SetJustInTime(ETrue);
test(t1.ExitType() == EExitPanic);
test(t1.ExitReason() == KErrBadHandle);
CLOSE_AND_WAIT(t1);
RThread t2;
User::SetJustInTime(EFalse);
test(t2.Create(_L("Handle2Test"), SendBadHandle2, KDefaultStackSize, KHeapSize, KHeapSize, NULL) == KErrNone);
t2.Logon(rs);
t2.Resume();
User::WaitForRequest(rs);
User::SetJustInTime(ETrue);
test(t2.ExitType() == EExitPanic);
test(t2.ExitReason() == KErrBadHandle);
CLOSE_AND_WAIT(t2);
RThread t3;
User::SetJustInTime(EFalse);
test(t3.Create(_L("Handle2Test"), SendBadHandle3, KDefaultStackSize, KHeapSize, KHeapSize, NULL) == KErrNone);
t3.Logon(rs);
t3.Resume();
User::WaitForRequest(rs);
User::SetJustInTime(ETrue);
test(t3.ExitType() == EExitPanic);
test(t3.ExitReason() == KErrBadHandle);
CLOSE_AND_WAIT(t3);
RThread t4;
User::SetJustInTime(EFalse);
test(t4.Create(_L("Handle2Test"), SendBadHandle4, KDefaultStackSize, KHeapSize, KHeapSize, NULL) == KErrNone);
t4.Logon(rs);
t4.Resume();
User::WaitForRequest(rs);
User::SetJustInTime(ETrue);
test(t4.ExitType() == EExitPanic);
test(t4.ExitReason() == KErrBadHandle);
CLOSE_AND_WAIT(t4);
RThread t5;
User::SetJustInTime(EFalse);
test(t5.Create(_L("Handle2Test"), SendBadHandle5, KDefaultStackSize, KHeapSize, KHeapSize, NULL) == KErrNone);
t5.Logon(rs);
t5.Resume();
User::WaitForRequest(rs);
User::SetJustInTime(ETrue);
test(t5.ExitType() == EExitPanic);
test(t5.ExitReason() == KErrBadHandle);
CLOSE_AND_WAIT(t5);
RThread t6;
User::SetJustInTime(EFalse);
test(t6.Create(_L("Handle2Test"), SendBadHandle6, KDefaultStackSize, KHeapSize, KHeapSize, NULL) == KErrNone);
t6.Logon(rs);
t6.Resume();
User::WaitForRequest(rs);
User::SetJustInTime(ETrue);
test(t6.ExitType() == EExitPanic);
test(t6.ExitReason() == KErrBadHandle);
CLOSE_AND_WAIT(t6);
User::SetJustInTime(ETrue);
test.End();
}
LOCAL_C void DoTestsL()
//
// Call all tests
//
{
Test1();
Test2();
Test3();
}
GLDEF_C void CallTestsL(void)
//
// Test resource counting
//
{
test.Title();
test.Start(_L("Starting T_RCOUNT test"));
DoTestsL();
test.End();
test.End();
test.Close();
return;
}