sl@0: // Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // f32test\loader\handshare.cpp sl@0: // sl@0: // sl@0: sl@0: #include sl@0: #include sl@0: #include "handshare.h" sl@0: sl@0: #ifdef __VC32__ sl@0: #pragma warning(disable:4706) sl@0: #endif sl@0: sl@0: sl@0: sl@0: GLDEF_D RTest test(_L("HANDSHARE_SVR")); sl@0: sl@0: #define PANIC() FHSvrPanic(__LINE__) sl@0: #define FHS_ASSERT(c) ((void)((c)||(PANIC(),0))) sl@0: sl@0: const TTimeIntervalMicroSeconds32 KHalfSecond(500000); sl@0: sl@0: const TInt KHeapSize=0x2000; sl@0: sl@0: void FHSvrPanic(TInt aLine) sl@0: { sl@0: User::Panic(_L("FHServer"),aLine); sl@0: } sl@0: sl@0: LOCAL_D TInt gTestDrive; sl@0: sl@0: /****************************************************************************** sl@0: * Class Definitions sl@0: ******************************************************************************/ sl@0: sl@0: sl@0: class CFHServer : public CServer2 sl@0: { sl@0: public: sl@0: static CFHServer* NewL(); sl@0: void ConstructL(); sl@0: virtual ~CFHServer(); sl@0: virtual CSession2* NewSessionL(const TVersion& aVersion, const RMessage2& aMessage) const; sl@0: virtual TInt RunError(TInt aError); sl@0: private: sl@0: CFHServer(); sl@0: }; sl@0: sl@0: class CFHSession : public CSession2 sl@0: { sl@0: public: sl@0: virtual ~CFHSession(); sl@0: virtual void CreateL(); sl@0: virtual void ServiceL(const RMessage2& aMessage); sl@0: public: sl@0: sl@0: void GetFileHandle(const RMessage2& aMsg); sl@0: void GetFileHandle2(const RMessage2& aMsg); sl@0: void PassFileHandle(const RMessage2& aMsg); sl@0: void PassFileHandleProcess(const RMessage2& aMsg); sl@0: void PassInvalidFileHandle(const RMessage2& aMsg); sl@0: }; sl@0: sl@0: // a second server so we can test passing file handles from sl@0: // client to server to server2 sl@0: class CFHServer2 : public CServer2 sl@0: { sl@0: public: sl@0: static CFHServer2* NewL(); sl@0: void ConstructL(); sl@0: virtual ~CFHServer2(); sl@0: virtual CSession2* NewSessionL(const TVersion& aVersion, const RMessage2& aMessage) const; sl@0: virtual TInt RunError(TInt aError); sl@0: private: sl@0: CFHServer2(); sl@0: public: sl@0: }; sl@0: sl@0: sl@0: class CFHSession2 : public CSession2 sl@0: { sl@0: public: sl@0: virtual ~CFHSession2(); sl@0: virtual void CreateL(); sl@0: virtual void ServiceL(const RMessage2& aMessage); sl@0: public: sl@0: void PassFileHandle(const RMessage2& aMsg); sl@0: void GetFileHandle(const RMessage2& aMsg); sl@0: }; sl@0: sl@0: sl@0: /****************************************************************************** sl@0: * Class CFHSession/CFHServer sl@0: ******************************************************************************/ sl@0: void ExceptionHandler(TExcType) sl@0: { sl@0: User::Leave(KErrGeneral); sl@0: } sl@0: sl@0: sl@0: sl@0: CFHSession::~CFHSession() sl@0: { sl@0: } sl@0: sl@0: void CFHSession::CreateL() sl@0: { sl@0: sl@0: } sl@0: sl@0: void CFHSession::ServiceL(const RMessage2& aMessage) sl@0: { sl@0: __UHEAP_MARK; sl@0: TInt mid=aMessage.Function(); sl@0: switch(mid) sl@0: { sl@0: case RFileHandleSharer::EMsgGetFileHandle: sl@0: GetFileHandle(aMessage); sl@0: break; sl@0: sl@0: case RFileHandleSharer::EMsgGetFileHandle2: sl@0: GetFileHandle2(aMessage); sl@0: break; sl@0: sl@0: case RFileHandleSharer::EMsgPassFileHandle: sl@0: PassFileHandle(aMessage); sl@0: break; sl@0: sl@0: case RFileHandleSharer::EMsgPassFileHandleProcess: sl@0: PassFileHandleProcess(aMessage); sl@0: break; sl@0: sl@0: case RFileHandleSharer::EMsgPassInvalidFileHandle: sl@0: PassInvalidFileHandle(aMessage); sl@0: break; sl@0: sl@0: case RFileHandleSharer::EMsgExit: sl@0: { sl@0: // stop server2 sl@0: RFileHandleSharer2 handsvr2; sl@0: TInt r=handsvr2.Connect(); sl@0: test(r==KErrNone); sl@0: r = handsvr2.Exit(); sl@0: test(r==KErrNone || r == KErrServerTerminated); sl@0: handsvr2.Close(); sl@0: sl@0: aMessage.Complete(KErrNone); sl@0: sl@0: CActiveScheduler::Stop(); sl@0: } sl@0: break; sl@0: sl@0: case RFileHandleSharer::EMsgSync: sl@0: aMessage.Complete(KErrNone); sl@0: break; sl@0: sl@0: case RFileHandleSharer::EMsgDrive: sl@0: gTestDrive=aMessage.Int0(); sl@0: aMessage.Complete(KErrNone); sl@0: break; sl@0: default: sl@0: break; sl@0: } sl@0: __UHEAP_MARKEND; sl@0: } sl@0: sl@0: sl@0: // sl@0: // Returns session and relevant file handle to Client in read mode sl@0: // This is to allow the client to test the deprcated function RFile::Adopt() sl@0: void CFHSession::GetFileHandle(const RMessage2& aMsg) sl@0: { sl@0: test.Printf(_L("Get file handle")); sl@0: sl@0: // get the requested file mode sl@0: TInt fileMode = aMsg.Int1(); sl@0: sl@0: RFs fs; sl@0: TInt r=fs.Connect(); sl@0: r=fs.CreatePrivatePath(gTestDrive); sl@0: test(r==KErrNone); sl@0: r=fs.SetSessionToPrivate(gTestDrive); sl@0: test(r==KErrNone); sl@0: r=fs.ShareProtected(); sl@0: test(r==KErrNone); sl@0: RFile file1; sl@0: r=file1.Create(fs,KSvrFileName,EFileWrite); sl@0: test(r==KErrNone || r==KErrAlreadyExists); sl@0: if (r==KErrAlreadyExists) sl@0: { sl@0: r=file1.Open(fs,KSvrFileName, EFileWrite); sl@0: test(r==KErrNone); sl@0: } sl@0: r=file1.Write(KTestData1()); sl@0: test(r==KErrNone); sl@0: file1.Close(); sl@0: sl@0: r=file1.Open(fs,KSvrFileName, fileMode); sl@0: test(r==KErrNone); sl@0: sl@0: TInt fssh=file1.SubSessionHandle(); sl@0: r=aMsg.Write(0, TPckgC(fssh)); sl@0: test(r==KErrNone); sl@0: aMsg.Complete(fs); sl@0: fs.Close(); sl@0: } sl@0: sl@0: // sl@0: // Returns a file handle from server2 sl@0: // sl@0: void CFHSession::GetFileHandle2(const RMessage2& aMsg) sl@0: { sl@0: test.Next(_L("RFile::AdoptFromServer()")); sl@0: sl@0: // pass the request on to FHServer2 - this will create a file sl@0: // which we can then adopt before returning it to the client sl@0: sl@0: // get the requested file mode sl@0: TInt fileMode = aMsg.Int1(); sl@0: sl@0: RFileHandleSharer2 handsvr2; sl@0: TInt r = handsvr2.Connect(); sl@0: test(r==KErrNone); sl@0: sl@0: TInt ssh; sl@0: TInt fsh = handsvr2.GetFileHandle(ssh, TFileMode(fileMode)); sl@0: test(fsh >= 0); sl@0: sl@0: // adopt the file from FHServer2 sl@0: RFile file; sl@0: r=file.AdoptFromServer(fsh, ssh); sl@0: test(r==KErrNone); sl@0: sl@0: test.Next(_L("RFile::TransferToClient()")); sl@0: sl@0: // transfer the file to the client sl@0: r = file.TransferToClient(aMsg, 0); sl@0: test(r==KErrNone); sl@0: sl@0: // test we can still use the file sl@0: TInt pos = 0; sl@0: r = file.Seek(ESeekStart, pos); sl@0: test(r==KErrNone); sl@0: TBuf8<100> rbuf; sl@0: r=file.Read(0,rbuf); sl@0: test(r==KErrNone); sl@0: r=rbuf.CompareF(KTestData1()); sl@0: test(r==KErrNone); sl@0: sl@0: handsvr2.Close(); sl@0: sl@0: file.Close(); sl@0: sl@0: RDebug::Print(_L("completed")); sl@0: } sl@0: sl@0: void CFHSession::PassFileHandle(const RMessage2& aMsg) sl@0: // sl@0: // Adopts file from test program and tests what it can and can't do sl@0: // Uses new AdoptFromClient() API sl@0: // sl@0: { sl@0: test.Next(_L("RFile::AdoptFromClient()")); sl@0: sl@0: // connect to FHServer2 sl@0: RFileHandleSharer2 handsvr2; sl@0: TInt r = handsvr2.Connect(); sl@0: test(r==KErrNone); sl@0: sl@0: RFile file; sl@0: sl@0: // Message slot 0 is a RFs handle sl@0: // Message slot 1 is a RFile Subsession handle (RFile::SubSessionHandle()) sl@0: r = file.AdoptFromClient(aMsg, 0, 1); sl@0: test(r==KErrNone); sl@0: sl@0: sl@0: sl@0: TBuf8<100> rbuf; sl@0: r=file.Read(0,rbuf); sl@0: test(r==KErrNone); sl@0: r=rbuf.CompareF(KTestData()); sl@0: test(r==KErrNone); sl@0: r=file.Write(KTestData1()); sl@0: test(r==KErrAccessDenied); sl@0: r=file.ChangeMode(EFileWrite); sl@0: test(r==KErrArgument); sl@0: r=file.Rename(_L("\\newname.txt")); sl@0: test(r==KErrPermissionDenied || r==KErrAccessDenied); sl@0: // should try a delete sl@0: sl@0: // pass the file handle to FHServer2 sl@0: test.Next(_L("RFile::TransferToServer()")); sl@0: sl@0: TIpcArgs ipcArgs; sl@0: file.TransferToServer(ipcArgs, 0, 1); sl@0: r = handsvr2.PassFileHandle(ipcArgs); sl@0: test(r==KErrNone); sl@0: sl@0: TInt pos = 0; sl@0: r = file.Seek(ESeekStart, pos); sl@0: test(r==KErrNone); sl@0: r=file.Read(0,rbuf); sl@0: test(r==KErrNone); sl@0: r=rbuf.CompareF(KTestData()); sl@0: test(r==KErrNone); sl@0: sl@0: file.Close(); sl@0: sl@0: handsvr2.Close(); sl@0: sl@0: aMsg.Complete(KErrNone); sl@0: } sl@0: sl@0: // sl@0: // Adopts file from test program and tests what it can and can't do sl@0: // Uses new AdoptFromCreator() API sl@0: // sl@0: void CFHSession::PassFileHandleProcess(const RMessage2& aMsg) sl@0: { sl@0: test.Next(_L("RFile::AdoptFromCreator()")); sl@0: sl@0: RFile file; sl@0: TInt r = file.AdoptFromCreator(1, 2); sl@0: test(r == KErrNone); sl@0: sl@0: TBuf8<100> rbuf; sl@0: r=file.Read(0,rbuf); sl@0: test(r==KErrNone); sl@0: r=rbuf.CompareF(KTestData()); sl@0: test(r==KErrNone); sl@0: sl@0: test.Next(_L("RFile::Rename()")); sl@0: sl@0: // define a filename in our private path sl@0: RFs fs; sl@0: r=fs.Connect(); sl@0: test(r==KErrNone); sl@0: sl@0: TFileName sessionp; sl@0: fs.SessionPath(sessionp); sl@0: r = fs.MkDirAll(sessionp); sl@0: test(r==KErrNone || r==KErrAlreadyExists); sl@0: sl@0: r=fs.ShareProtected(); sl@0: test(r==KErrNone); sl@0: sl@0: r=fs.CreatePrivatePath(gTestDrive); sl@0: test(r==KErrNone); sl@0: r=fs.SetSessionToPrivate(gTestDrive); sl@0: test(r==KErrNone); sl@0: sl@0: TPath newPath; sl@0: fs.PrivatePath(newPath); sl@0: TFileName newFileName; sl@0: newFileName = newPath; sl@0: newFileName.Append(_L("newname.txt")); sl@0: sl@0: // delete the file before we try to rename anything to it sl@0: r = fs.Delete(newFileName); sl@0: test(r == KErrNone || r == KErrNotFound); sl@0: sl@0: r=file.Rename(newFileName); sl@0: test(r==KErrNone); sl@0: sl@0: file.Close(); sl@0: sl@0: // Next verify that we can delete the file (which should now sl@0: // have been moved to our private directory) sl@0: test.Next(_L("RFs::Delete()")); sl@0: r = fs.Delete(newFileName); sl@0: test(r == KErrNone); sl@0: sl@0: fs.Close(); sl@0: sl@0: sl@0: aMsg.Complete(KErrNone); sl@0: } sl@0: sl@0: void CFHSession::PassInvalidFileHandle(const RMessage2& aMsg) sl@0: // sl@0: // Attempts to adopt an invalid file handle from test program sl@0: // and tests that KErrBadHandle is returned by AdoptFromClient() sl@0: // sl@0: { sl@0: test.Next(_L("PassInvalidFileHandle - RFile::AdoptFromClient()")); sl@0: sl@0: RFile file; sl@0: sl@0: // Message slot 0 is a RFs handle sl@0: // Message slot 1 is a RFile Subsession handle (RFile::SubSessionHandle()) sl@0: TInt r = file.AdoptFromClient(aMsg, 0, 1); sl@0: test(r==KErrBadHandle); sl@0: sl@0: sl@0: aMsg.Complete(r); sl@0: } sl@0: sl@0: CFHServer* CFHServer::NewL() sl@0: { sl@0: CFHServer* server = new (ELeave) CFHServer; sl@0: CleanupStack::PushL(server); sl@0: server->ConstructL(); sl@0: CleanupStack::Pop(server); sl@0: return server; sl@0: } sl@0: sl@0: void CFHServer::ConstructL() sl@0: { sl@0: } sl@0: sl@0: CFHServer::CFHServer() sl@0: : CServer2(0,ESharableSessions) sl@0: { sl@0: } sl@0: sl@0: CFHServer::~CFHServer() sl@0: { sl@0: } sl@0: sl@0: CSession2* CFHServer::NewSessionL(const TVersion& aVersion, const RMessage2&) const sl@0: // sl@0: // Create New Session sl@0: // sl@0: { sl@0: (void)aVersion; sl@0: CFHSession* s = new (ELeave) CFHSession; sl@0: return s; sl@0: } sl@0: sl@0: _LIT(KErr,"FHSERVER_ERR"); sl@0: CFHServer2* CFHServer2::NewL() sl@0: { sl@0: CFHServer2* server = new (ELeave) CFHServer2; sl@0: CleanupStack::PushL(server); sl@0: server->ConstructL(); sl@0: CleanupStack::Pop(server); sl@0: return server; sl@0: } sl@0: sl@0: void CFHServer2::ConstructL() sl@0: { sl@0: } sl@0: sl@0: TInt CFHServer::RunError(TInt aError) sl@0: { sl@0: User::Panic(KErr,aError); sl@0: return 0; sl@0: } sl@0: sl@0: // File handle server #2 sl@0: CFHServer2::CFHServer2() sl@0: : CServer2(0,ESharableSessions) sl@0: { sl@0: } sl@0: sl@0: CFHServer2::~CFHServer2() sl@0: { sl@0: } sl@0: sl@0: CSession2* CFHServer2::NewSessionL(const TVersion& aVersion, const RMessage2&) const sl@0: // sl@0: // Create New Session sl@0: // sl@0: { sl@0: (void)aVersion; sl@0: CFHSession2* s = new (ELeave) CFHSession2; sl@0: return s; sl@0: } sl@0: sl@0: _LIT(KErr2,"FHSERVER2_ERR"); sl@0: TInt CFHServer2::RunError(TInt aError) sl@0: { sl@0: User::Panic(KErr2,aError); sl@0: return 0; sl@0: } sl@0: sl@0: CFHSession2::~CFHSession2() sl@0: { sl@0: } sl@0: sl@0: void CFHSession2::CreateL() sl@0: { sl@0: sl@0: } sl@0: sl@0: void CFHSession2::ServiceL(const RMessage2& aMessage) sl@0: { sl@0: __UHEAP_MARK; sl@0: TInt mid=aMessage.Function(); sl@0: switch(mid) sl@0: { sl@0: case RFileHandleSharer::EMsgPassFileHandle: sl@0: PassFileHandle(aMessage); sl@0: break; sl@0: sl@0: case RFileHandleSharer::EMsgGetFileHandle: sl@0: GetFileHandle(aMessage); sl@0: break; sl@0: sl@0: case RFileHandleSharer::EMsgExit: sl@0: aMessage.Complete(KErrNone); sl@0: CActiveScheduler::Stop(); sl@0: break; sl@0: sl@0: default: sl@0: break; sl@0: } sl@0: __UHEAP_MARKEND; sl@0: } sl@0: sl@0: sl@0: // sl@0: // Adopts file from server 1 sl@0: // sl@0: void CFHSession2::PassFileHandle(const RMessage2& aMsg) sl@0: { sl@0: RFile file; sl@0: sl@0: // Message slot 0 is a RFs handle sl@0: // Message slot 1 is a RFile Subsession handle (RFile::SubSessionHandle()) sl@0: TInt r = file.AdoptFromClient(aMsg, 0, 1); sl@0: if (r != KErrNone) sl@0: { sl@0: aMsg.Complete(r); sl@0: return; sl@0: } sl@0: sl@0: sl@0: TBuf8<100> rbuf; sl@0: sl@0: if (r == KErrNone) sl@0: r=file.Read(0,rbuf); sl@0: sl@0: if (r == KErrNone) sl@0: r = rbuf.CompareF(KTestData()); sl@0: sl@0: if (r == KErrNone) sl@0: { sl@0: r = file.Write(KTestData1()); sl@0: if (r == KErrAccessDenied) sl@0: r = KErrNone; sl@0: } sl@0: sl@0: if (r == KErrNone) sl@0: { sl@0: r = file.ChangeMode(EFileWrite); sl@0: if (r == KErrArgument) sl@0: r = KErrNone; sl@0: } sl@0: sl@0: if (r == KErrNone) sl@0: { sl@0: r = file.Rename(_L("\\newname.txt")); sl@0: if (r == KErrPermissionDenied || r == KErrAccessDenied) sl@0: r = KErrNone; sl@0: } sl@0: sl@0: file.Close(); sl@0: sl@0: aMsg.Complete(r); sl@0: } sl@0: sl@0: sl@0: void CFHSession2::GetFileHandle(const RMessage2& aMsg) sl@0: // sl@0: // Returns a file handle in write mode sl@0: // sl@0: { sl@0: RFs fs; sl@0: TInt r = fs.Connect(); sl@0: sl@0: if (r == KErrNone) sl@0: r = fs.CreatePrivatePath(gTestDrive); sl@0: sl@0: if (r == KErrNone) sl@0: r = fs.SetSessionToPrivate(gTestDrive); sl@0: sl@0: if (r == KErrNone) sl@0: r = fs.ShareProtected(); sl@0: sl@0: // make sure file exists & has valid data in it sl@0: RFile file1; sl@0: if (r == KErrNone) sl@0: r = file1.Replace(fs,KSvrFileName,EFileWrite); sl@0: sl@0: if (r == KErrNone) sl@0: r = file1.Write(KTestData1()); sl@0: sl@0: file1.Close(); sl@0: sl@0: sl@0: // re-open the file with the mode the client has requested & pass it to the client sl@0: TFileMode fileMode = TFileMode(aMsg.Int1()); sl@0: if (r == KErrNone) sl@0: r = file1.Open(fs,KSvrFileName, fileMode); sl@0: if (r == KErrNone) sl@0: r = file1.TransferToClient(aMsg, 0); sl@0: file1.Close(); sl@0: sl@0: fs.Close(); sl@0: sl@0: if (r != KErrNone) sl@0: aMsg.Complete(r); sl@0: } sl@0: sl@0: LOCAL_C TInt FHServer2(TAny * /*anArg*/) sl@0: { sl@0: RTest test(_L("FHServer2")); sl@0: sl@0: // Remember the number of open handles. Just for a sanity check .... sl@0: TInt start_thc, start_phc; sl@0: RThread().HandleCount(start_phc, start_thc); sl@0: sl@0: sl@0: CTrapCleanup* cleanup; sl@0: cleanup=CTrapCleanup::New(); sl@0: sl@0: CActiveScheduler* sched=new CActiveScheduler; sl@0: FHS_ASSERT(sched); sl@0: CActiveScheduler::Install(sched); sl@0: sl@0: CFHServer2* svr2 = NULL; sl@0: TRAP_IGNORE(svr2 = CFHServer2::NewL()); sl@0: FHS_ASSERT(svr2); sl@0: FHS_ASSERT(svr2->Start(_L("FHServer2"))==KErrNone); sl@0: sl@0: CActiveScheduler::Start(); sl@0: sl@0: delete svr2; sl@0: delete sched; sl@0: sl@0: delete cleanup; sl@0: sl@0: // Sanity check for open handles sl@0: TInt end_thc, end_phc; sl@0: RThread().HandleCount(end_phc, end_thc); sl@0: test(start_thc == end_thc); sl@0: test(start_phc == end_phc); sl@0: // and also for pending requests ... sl@0: test(RThread().RequestCount() == 0); sl@0: sl@0: sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: sl@0: GLDEF_C TInt E32Main() sl@0: // sl@0: // Test Server for file handle sharing sl@0: // sl@0: { sl@0: test.Title(); sl@0: test.Start(_L("Starting FHServer...")); sl@0: sl@0: // Remember the number of open handles. Just for a sanity check .... sl@0: TInt start_thc, start_phc; sl@0: RThread().HandleCount(start_phc, start_thc); sl@0: sl@0: CTrapCleanup* cleanup=CTrapCleanup::New(); sl@0: sl@0: FHS_ASSERT(cleanup); sl@0: CActiveScheduler* sched=new CActiveScheduler; sl@0: FHS_ASSERT(sched); sl@0: CActiveScheduler::Install(sched); sl@0: sl@0: // start server1 sl@0: CFHServer* svr = NULL; sl@0: TRAP_IGNORE(svr = CFHServer::NewL()); sl@0: FHS_ASSERT(svr); sl@0: FHS_ASSERT(svr->Start(_L("FHServer"))==KErrNone); sl@0: sl@0: test.Title(); sl@0: test.Start(_L("Starting tests...")); sl@0: sl@0: // start server2 in a seperate thread sl@0: RThread server2Thread; sl@0: TInt r = server2Thread.Create(_L("FHServer2"), FHServer2, KDefaultStackSize, KHeapSize, KHeapSize, NULL); sl@0: test(r==KErrNone); sl@0: TRequestStatus statq; sl@0: server2Thread.Logon(statq); sl@0: server2Thread.Resume(); sl@0: sl@0: CActiveScheduler::Start(); sl@0: sl@0: sl@0: // wait for server2's thread to end gracefully sl@0: User::WaitForRequest(statq); sl@0: sl@0: sl@0: server2Thread.Close(); sl@0: sl@0: RFs cleanupfs; sl@0: r = cleanupfs.Connect(); sl@0: test(r==KErrNone); sl@0: r=cleanupfs.SetSessionToPrivate(gTestDrive); sl@0: test(r==KErrNone); sl@0: r=cleanupfs.Delete(KSvrFileName); sl@0: test(r==KErrNone || r==KErrNotFound); sl@0: cleanupfs.Close(); sl@0: sl@0: sl@0: test.End(); sl@0: sl@0: delete svr; sl@0: delete sched; sl@0: delete cleanup; sl@0: sl@0: // Sanity check for open handles and pending requests sl@0: TInt end_thc, end_phc; sl@0: RThread().HandleCount(end_phc, end_thc); sl@0: test(start_thc == end_thc); sl@0: test(start_phc == end_phc); sl@0: test(RThread().RequestCount() == 0); sl@0: sl@0: return 0; sl@0: }