--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/euser/rpipe.cpp Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,1111 @@
+// Copyright (c) 2006-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:
+//
+
+/**
+ @file rpipe.cpp
+ @internalTechnology
+*/
+
+#include <e32def.h>
+#include <e32def_private.h>
+#include "rpipe.h"
+
+EXPORT_C TInt RPipe::Init()
+/**
+Static method to load the pipe device driver.
+
+@param None
+
+@return KErrNone If the pipe is successfully loaded, otherwise one of the
+ system wide error code.
+*/
+ {
+ _LIT(KDriverLddFileName,"PIPELIB");
+ return User::LoadLogicalDevice(KDriverLddFileName);
+ }
+
+
+EXPORT_C TInt RPipe::Create( TInt aSize, RPipe& aReader, RPipe& aWriter, TOwnerType aTypeR, TOwnerType aTypeW)
+/**
+Static method to create a new, unnamed pipe.
+By default, any thread in the process can use the handle to access the Pipe. However,
+specifying EOwnerThread as the second and fourth parameter to this function, means
+that only the creating thread can use this handle to access the Pipe.
+
+@param aReader Handle to the read end of the pipe. If the call is successful,
+ this handle will be opened for reading.
+@param aWriter Handle to the write end of the pipe. If the call is successful,
+ this handle will be opened for writing.
+@param aTypeR, aTypeW The type of the ownership of the handle to be created for the
+ read and write
+@param aSize Size of the pipe to be created, in bytes.
+
+@return KErrNone Pipe successfully created and the read and write handles opened,
+ KErrOverflow Maximum number of pipes has been reached.
+ KErrNoMemory Insufficient memory to create pipe
+ KErrArgument If the specified size is negative or zero
+ KErrInUse The current handle has already been opened.
+ otherwise one of the other system wide error codes
+*/
+
+ {
+ TInt err = aReader.Create(aSize, aTypeR);
+ if (err != KErrNone )
+ return err;
+ else
+ {
+ err = aWriter.Open(aReader, aTypeW);
+ if(err!= KErrNone)
+ aReader.Close();
+ }
+ return err;
+ }
+
+TInt RPipe::Create(TInt aSize, TOwnerType aType)
+/**
+Creates a Kernel side pipe and opens a handle for reading.
+By default any thread in the process can use the handle to access to Read the Pipe.
+However, specifying EOwnerThread as the second parameter to this function, means
+that only the creating thread can use this handle to access the pipe.
+
+@param aSize Size of the pipe to create, in bytes.
+
+@param aType The type of the handle to be created for the reading
+ end of the pipe
+
+@return KErrNone Pipe successfully created and handle opened for reading,
+ KErrInUse The current handle has already been opened.
+ KErrOverflow Maximum number of pipes has been reached.
+ KErrNoMemory Insufficient memory to create pipe
+ KErrArgument If the specified size is negative or zero
+ otherwise one of the other system wide error code
+*/
+ {
+
+ // Check if the current handle is already opened for reading/writing
+ if ( iHandle && HandleType())
+ return KErrInUse;
+
+ if(aSize <= 0 )
+ return KErrArgument;
+
+ // Perform the capability check and create the channel
+ TInt err = DoCreate(Name(), VersionRequired(), KNullUnit, NULL, NULL, aType, ETrue);
+ if (err!= KErrNone)
+ return err;
+
+ // Create an un-named pipe with the specified size
+ err = DoControl(ECreateUnNamedPipe, (TAny*)&aSize);
+ if (err>0)
+ {
+ iSize = DoControl(ESize);
+ iHandleType = EReadChannel;
+ iPipeHandle = err;
+ err = KErrNone;
+ }
+ else
+ {
+ Close();
+ }
+ return err;
+ }
+
+
+EXPORT_C TInt RPipe::Open(RMessagePtr2 aMessage, TInt aParam, TOwnerType aType)
+/**
+Opens a handle to pipe using a handle number sent by a client to a server.
+This function is called by the server.
+
+@param aMessage The message pointer.
+
+@param aParam An index specifying which of the four message arguments contains the handle number.
+
+@param aType An enumeration whose enumerators define the ownership of this logical channel handle.
+ If not explicitly specified, EOwnerProcess is taken as default.
+@return KErrNone if successful;
+ KErrArgument if the value of aParam is outside the range 0-3;
+ KErrBadHandle if not a valid handle;
+ otherwise one of the other system-wide error codes.
+
+
+*/
+ {
+ TInt err = RBusLogicalChannel::Open(aMessage, aParam, aType);
+ if (err)
+ {
+ return err;
+ }
+ err = DoControl(RPipe::EGetPipeInfo,&iHandleType,&iSize);
+ return err;
+
+ }
+
+
+EXPORT_C TInt RPipe::Open(TInt aArgumentIndex, TOwnerType aType)
+/**
+Opens the handle to pipe which is passed by a process to child process using
+RProcess.SetParameter function call. Pipe handle type remains same(i.e. if read handle is passed
+by process then read handle will be open).
+
+@param aArgumentIndex An index that identifies the slot in the process environment
+ data that contains the handle number. This is a value relative
+ to zero, i.e. 0 is the first item/slot. This can range from 0 to 15.
+
+@param aType The type of the handle to be created for the read/write end
+
+@return KErrNone Pipe successfully created,
+ otherwise of the other system wide error code.
+*/
+ {
+
+ TInt err = RBusLogicalChannel::Open(aArgumentIndex,aType);
+ if (err)
+ {
+ return err;
+ }
+ err = DoControl(RPipe::EGetPipeInfo,&iHandleType,&iSize);
+ return err;
+ }
+
+TInt RPipe::Open(const RPipe& aReader, TOwnerType aType)
+/**
+Opens a handle to write to a pipe. The pipe must have been created previously.
+By default any thread in the process can use the handle to access to write to
+the pipe. However, specifying EOwnerThread as the second parameter to this function,
+means that only the opening thread can use this handle to write to the pipe.
+
+@param aReader Handle to the reading end of the pipe.
+
+@param aType The type of the handle to be created for the write end
+
+@return KErrNone Pipe successfully created,
+ KErrInUse The current handle has already been opened
+ KErrAccessDenied The read handle is not open for reading
+ otherwise of the other system wide error code.
+*/
+ {
+ // Check if the current handle is already opened for reading/writing
+ if ( iHandle && HandleType())
+ return KErrInUse;
+
+ // Check the read handle
+
+ if (aReader.HandleType() != EReadChannel)
+ return KErrAccessDenied;
+
+ // Perform the capability check and create the channel
+ TInt err = DoCreate(Name(),VersionRequired(), KNullUnit, NULL, NULL, aType, ETrue);
+ if (err!= KErrNone)
+ return err;
+
+ // Obtained the handle number
+ TInt id = aReader.PipeHandle();
+
+
+ // Set the Write channel
+ err = DoControl(EOpenUnNamedPipe,(TAny*)&id);
+
+ if( err == KErrNone)
+ {
+ iSize = DoControl(ESize);
+ iHandleType = EWriteChannel;
+ iPipeHandle = id;
+
+ }
+ else
+ {
+ Close();
+ }
+
+
+ return err;
+ }
+
+
+// Methods to Support Named Pipe
+
+EXPORT_C TInt RPipe::Define(const TDesC& aName, TInt aSize)
+/**
+Static method to create a new, named pipe of a given size. Calling this method
+will create a new kernel object only. No user-side handles are created or opened.
+
+@param aName Name to be assigned to the Kernel-side pipe object.
+@param aSize Size of the pipe to create, in bytes.
+
+@return KErrNone Pipe successfully created.
+ KErrBadName If the length of aName is greater than KMaxFileName
+ or Null
+ KErrOverflow Maximum number of pipes has been reached
+ KErrNoMemory Insufficient memory to create pipe.
+ KErrArgument if Size is negative
+ KErrAlreadyExist If a pipe with the specified name already exist.
+ otherwise one of the other system wide error code.
+*/
+ {
+ // Code to check a valid Name field as per Symbian naming convention
+ TInt err = User::ValidateName(aName);
+ if(KErrNone!=err)
+ return err;
+
+ if((aName.Length() > KMaxKernelName) || (aName.Length() == 0))
+ return KErrBadName;
+
+ if(aSize <= 0)
+ return KErrArgument;
+
+ // Perform the capability check and create the channel
+ RPipe temp;
+ err = temp.DoCreate(Name(),VersionRequired(), KNullUnit, NULL, NULL);
+ if (err!= KErrNone)
+ return err;
+
+ // Define
+ TPipeInfoBuf aInfo;
+ aInfo().isize = aSize;
+ aInfo().iName.Copy(aName);
+
+ // Define the Named pipe
+ err = temp.DoControl(EDefineNamedPipe, (TAny*)&aInfo);
+ temp.Close();
+ return err;
+
+ }
+
+
+EXPORT_C TInt RPipe::Define( const TDesC& aName, TInt aSize, const TSecurityPolicy& aPolicy)
+/**
+Static method to create a new, named pipe of a given size. Calling this method
+will create a new kernel object only. No user-side handles are created or opened.
+
+@param aName Name to be assigned to the Kernel-side pipe object.
+@param aSize Size of the pipe to create, in bytes.
+
+@return KErrNone Pipe successfully created.
+ KErrBadName If the length of aName is greater than KMaxFileName
+ or Null
+ KErrOverflow Maximum number of pipes has been reached
+ KErrNoMemory Insufficient memory to create pipe.
+ KErrArgument if Size is negative
+ KErrPermissionDenied Not sufficient capabiliites
+ KErrAlreadyExist If a pipe with the specified name already exist.
+ otherwise one of the other system wide error code.
+*/
+ {
+
+ // Code to check a valid Name field as per Symbian naming convention
+ TInt err = User::ValidateName(aName);
+ if(KErrNone!=err)
+ return err;
+
+ if((aName.Length() > KMaxKernelName) || (aName.Length() == 0))
+ return KErrBadName;
+
+ if(aSize <= 0)
+ return KErrArgument;
+
+ // Perform the capability check and create the channel
+ RPipe temp;
+ err = temp.DoCreate(Name(),VersionRequired(), KNullUnit, NULL, NULL);
+ if (err!= KErrNone)
+ return err;
+
+ // Define
+ TPipeInfoBuf aInfo;
+ aInfo().isize = aSize;
+ aInfo().iName.Copy(aName);
+ err = temp.DoControl(EDefineNamedPipe, (TAny*)&aInfo, (TAny*)&aPolicy);
+ temp.Close();
+
+ return err;
+
+
+ }
+
+
+
+EXPORT_C TInt RPipe::Destroy( const TDesC& aName)
+/**
+Static method to destroy a previously created named pipe. Any data not read from
+the pipe will be discarded. This method will fail if there is any handles still
+open on the pipe or the calling thread as insufficient capabilities.
+
+@param aName Name of the Kernel-side pipe object to destroy
+
+@return KErrNone Pipe successfully destroyed
+ KErrInUse The pipe still has one or more handle open to it
+ KErrPermissionDenied Not sufficient capabiliites
+ KErrNotFound If no kernel pipe exist with the specified name
+ otherwise one of the other system wide error code.
+*/
+ {
+ // Code to check a valid Name field as per Symbian naming convention
+ TInt err = User::ValidateName(aName);
+ if(KErrNone!=err)
+ return err;
+
+ if((aName.Length() > KMaxKernelName) || (aName.Length() == 0))
+ return KErrBadName;
+
+ // Perform the capability check and create the channel
+ RPipe temp;
+ err = temp.DoCreate(Name(),VersionRequired(), KNullUnit, NULL, NULL);
+ if (err!= KErrNone)
+ return err;
+
+ TBuf8<KMaxKernelName> name;
+ name.Copy(aName);
+
+ // Destroy
+ err = temp.DoControl(EDestroyNamedPipe, (TAny*)&name, NULL);
+ temp.Close();
+
+ return err;
+
+ }
+
+
+EXPORT_C TInt RPipe::Open(const TDesC& aName, TMode aMode)
+/**
+Opens the pipe for the access mode specified. If the handle is opened to read or Write.
+The handle is opened regardless of whether or not there is a open handle at the other end.
+
+If the handle is opened as " Write but Fail On No Readers" the call will fail unless there
+is atleast one handle open for reading at the other end.
+
+@param aName Name of the kernel-side pipe object to destroy
+@param aMode Access mode for the handle.
+
+@return KErrNone Handle successfully opened.
+ KErrBadName If the length of aName is greater than KMaxFileName or Null
+ KErrInUse The pipe still has one or more handle open to it.
+ KErrPermissionDenied Not sufficient capabiliites
+ KErrNotFond If there is no kernel instance with the specified name
+ KErrNotReady Open Fails when no Readers is available while opening
+ With TMode = EOpenToWriteButFailOnNoReaders
+ otherwise one of the other system wide error code.
+
+*/
+ {
+
+ // Check if the current handle is already opened for reading/writing
+ if ( iHandle && HandleType())
+ return KErrInUse;
+
+ TInt err = User::ValidateName(aName);
+ if(KErrNone!=err)
+ return err;
+
+ if((aName.Length() > KMaxKernelName) || (aName.Length() == 0))
+ return KErrBadName;
+
+ // Perform the capability check and create the channel
+ err = DoCreate(Name(),VersionRequired(), KNullUnit, NULL, NULL);
+ if (err!= KErrNone)
+ return err;
+
+ TBuf8<KMaxKernelName> name;
+ name.Copy(aName);
+
+
+ if (aMode == EOpenToRead)
+ {
+ err = DoControl(EOpenToReadNamedPipe,(TAny*)&name);
+ if(err == KErrNone)
+ {
+ iSize = DoControl(ESize);
+ iHandleType = EReadChannel;
+ }
+ else
+ Close();
+ }
+ else if(aMode == EOpenToWrite)
+ {
+ err = DoControl(EOpenToWriteNamedPipe, (TAny*)&name);
+ if(err == KErrNone)
+ {
+ iSize = DoControl(ESize);
+ iHandleType = EWriteChannel;
+ }
+ else
+ Close();
+ }
+ else if (aMode == EOpenToWriteNamedPipeButFailOnNoReaders)
+ {
+ err = DoControl(EOpenToWriteButFailOnNoReaderNamedPipe, (TAny*)&name);
+ if(err == KErrNone)
+ {
+ iSize = DoControl(ESize);
+ iHandleType = EWriteChannel;
+ }
+ else
+ Close();
+ }
+ else
+ {
+ Close();
+ err = KErrArgument;
+ }
+ return err;
+ }
+
+
+
+EXPORT_C void RPipe::Wait(const TDesC& aName, TRequestStatus& aStatus)
+/**
+Block the thread until the other end of the pipe is opened for reading. If the other end
+is already opened for reading the call will not block and status will complete immediately
+This function will be deprecated , use WaitForReader.
+Please note that Wait API will open a valid Write End of the pipe if not opened already.
+User need not open write end of the pipe again after Wait call.
+
+
+@param aName Name of the kernel-side pipe object to wait for
+@param aStatus Status request that will complete when the other end is opened
+ for reading.
+
+@return KErrNone Request is successfully registered
+ KErrBadName If the length of aName is greater then KMaxFileName or NULL
+ KErrInUse A notifier of this type has already been registered.
+ KErrPermissionDenied Not sufficient capabiliites
+ otherwise one of the other system wide error code.
+*/
+ {
+ // To wait for Reader end pass flag as EWaitForReader.
+ TInt aFlag = EWaitForReader;
+ Wait(aName, aStatus , aFlag );
+ }
+
+
+EXPORT_C void RPipe::CancelWait()
+/**
+Cancel previous call to RPipe::Wait(), RPipe::WaitForReader (), RPipe::WaitForWriter ()
+
+@param None
+@return None
+*/
+ {
+ if(!iHandle)
+ return;
+ DoCancel(ECancelWaitNotification);
+ }
+
+
+
+// Generic Methods
+
+EXPORT_C void RPipe::Close()
+/**
+Close the handle. This method exhibits different behaviour depending upon whether the pipe
+is named or unnamed.
+Named pipes are allowed to persist without any open handles. Closing the last handle on a
+named pipe will not destroy the kernel-side object. For an unnamed pipe, closing the last
+handle will destroy the kernel-side pipe object. Any unread data in the pipe will be
+discarded.
+An attempt to close an unnamed pipe will have no effect. Closing a handle will not affect
+the state of any other handles that may be open on the pipe.
+
+@param None
+
+@return None
+*/
+ {
+ if(!iHandle)
+ return;
+ RHandleBase::Close();
+ }
+
+
+
+
+EXPORT_C TInt RPipe::MaxSize()
+/**
+Returns the total size, in bytes, of the Pipe
+@param None
+
+@return >= 0 Size of the pipe in bytes
+ KErrBadHandle The handle is not open
+ otherwise one of the other system wide error code.
+*/
+ {
+ if (!iHandle )
+ return KErrBadHandle;
+
+ if(iHandleType == EReadChannel || iHandleType == EWriteChannel)
+ return iSize;
+ else
+ return KErrAccessDenied;
+ }
+
+
+
+EXPORT_C TInt RPipe::Read(TDes8& aMsg, TInt aNumByte)
+/**
+This is non-blocking synchronous method to read aNumByte bytes from the pipe into the
+descriptor aMsg and returns the number of bytes read. If the pipe is empty the call will
+immediately return a value of zero to indicate that no data was read
+
+A successful RPipe::Read() operation will free up more space in the pipe.
+
+@param aMsg Descriptor to receive data
+@param aNumByte Number of bytes to be received.
+
+@return >0 Amount of data read from the pipe, in bytes.
+ KErrUnderFlow The pipe was empty, no data was read
+ KErrAccessDenied An attempt has been made to read from a handle
+ has been opened for writing.
+ KErrBadHandle An attempt has been made to read from a handle
+ that has not been opened.
+ KErrNotReady Write end is closed and Pipe is empty.
+ 0 No Data is available
+ otherwise one of the other system wide error code.
+*/
+ {
+ // Check for the error condition
+ if (!iHandle)
+ return KErrBadHandle;
+
+ // Check for KErrArgument
+ if(aNumByte > aMsg.MaxLength())
+ return KErrArgument;
+
+ if(iHandleType != EReadChannel)
+ return KErrAccessDenied;
+
+ return DoControl(ERead, (TAny*)&aMsg, (TAny*)&aNumByte);
+ }
+
+
+
+
+EXPORT_C TInt RPipe::Write( const TDesC8& aData, TInt aNumByte)
+/**
+This is non-blocking synchronous method to write data from aData. If the pipe is
+full it will return immediately with KErrOverFlow
+
+@param aData Descriptor from which data has to be written to the pipe
+
+@return >0 Amount of data written to the pipe, in bytes
+ KErrAccessDenied An attempt has been made to write to a handle that
+ has been opened for reading.
+ KErrArgument If the size is more then aData's length
+ KErrBadName
+ KErrOverFlow The pipe is full. No data was inserted into the pipe.
+ KErrBadHandle An attempt has been made to read from a handle that
+ has not been opened.
+ KErrCompletion If the specified size is greater then the available size.
+ KErrNotReady Read end is closed.
+ otherwise one of the other system wide error code.
+
+*/
+ {
+ // Check for the error condition
+ if (!iHandle)
+ return KErrBadHandle;
+
+ // Check for KErrArgument
+ if(aNumByte > aData.Length())
+ return KErrArgument;
+
+ if(iHandleType == EReadChannel)
+ return KErrAccessDenied;
+
+ return DoControl(EWrite, (TAny*)&aData, (TAny*)&aNumByte);
+
+ }
+
+
+EXPORT_C TInt RPipe::ReadBlocking( TDes8& aMsg, TInt aNumByte)
+/**
+This is synchronous, blocking read operation. If the pipe is empty the client thread will
+be blocked until data become available. A successful RPipe::ReadBlocking() operation will
+free up more space in the pipe. This method is accompanied by data notification method to
+complete the blocking mechanism
+
+@param aMsg Descriptor to receive data
+@param aNumByte Number of bytes to be received
+
+@return >0 Amount of data read from the pipe in bytes.
+ KErrAccessDenied Am attempt has been made to read from the handle that
+ has been opened for writing.
+ KErrBadHandle Am attempt has been made to read from a handle that has
+ not been opened.
+ KErrArgument if the size is negative.
+ KErrInUse If the call is active from some another thread.
+ KErrNotReady Write end is closed and Pipe is empty.
+ otherwise one of the system wide error code.
+*/
+ {
+
+ TRequestStatus stat = KRequestPending;
+ TInt err = KErrNone;
+
+ // Check for the error condition
+ if (!iHandle)
+ return KErrBadHandle;
+
+ if(aNumByte <= 0)
+ return KErrArgument;
+
+ if(iHandleType != EReadChannel)
+ return KErrAccessDenied;
+
+ // Asynchronous request to notify the data available.
+ do
+ {
+ stat = KRequestPending;
+ DoRequest(EReadBlocking, stat);
+ User::WaitForRequest(stat);
+ err = stat.Int();
+ if (err == KErrInUse || err == KErrNotReady)
+ {
+ return err;
+ }
+
+ // Synchronous read operation
+ err = DoControl(ERead, (TAny*)&aMsg, (TAny*)&aNumByte);
+ if (err == KErrNotReady)
+ return err;
+
+ } while (err == 0);
+
+ return err;
+ }
+
+
+
+EXPORT_C TInt RPipe::WriteBlocking(const TDesC8& aData, TInt aNumByte)
+/**
+This is a synchronous, blocking write operation. It will attempt to
+write aNumByte's worth of data to the pipe, waiting till space is available.
+If aNumByte is less than or equal to the pipe size, MaxSize(), the write
+shall be atomic (w.r.t other threads sharing this channel), otherwise
+the data will be split into multiple atomic writes of pipe size
+(except, of course, if less than MaxSize bytes of data remain to be written).
+
+@param aData Descriptor from which data has to be written to the pipe.
+@param aNumByte Amount of data to be written to the pipe
+
+@return >0 Amount of data written to the pipe, in bytes.
+ KErrAccessDenied An attempt has been made to write to a handle that
+ has been opened for reading.
+ KErrBadHandle An attempt has been made to read from a handle that has
+ not been open.
+ KErrArgument if the size is negative.
+ KErrNotReady Read end is closed.
+ otherwise one of the other system wide error code.
+*/
+ {
+ TBool first = ETrue;
+ TRequestStatus stat = KRequestPending;
+ TInt err = 0;
+ TInt index = 0;
+ TInt writeindex =0;
+ TPtrC8 tmp;
+ TInt r = aNumByte;
+
+ // Check for the error condition
+ if (!iHandle)
+ return KErrBadHandle;
+
+
+ if(aNumByte <= 0)
+ return KErrArgument;
+
+
+ if(iHandleType == EReadChannel)
+ return KErrAccessDenied;
+
+ if (aNumByte <= iSize)
+ writeindex = aNumByte;
+ else
+ writeindex = iSize;
+
+ do
+ {
+ // Asynchronous request to notify the space available.
+ stat = KRequestPending;
+ DoRequest(EWriteBlocking, stat,(TAny*)&writeindex);
+ User::WaitForRequest(stat);
+ err = stat.Int();
+ if (err == KErrInUse || err == KErrNotReady)
+ {
+ return err;
+ }
+
+ // Synchronous write operation
+ tmp.Set(aData.Ptr()+index, writeindex);
+ err = DoControl(EWrite, (TAny*)&tmp, (TAny*)&writeindex);
+ if(err == KErrNotReady)
+ {
+ return err;
+ }
+ else
+ {
+ if ( err == aNumByte)
+ {
+ first = EFalse;
+ }
+ else
+ {
+ index = index + err;
+ aNumByte = r - index;
+ if(aNumByte < iSize)
+ writeindex = aNumByte;
+ }
+ }
+ }while(first);
+
+ return r;
+ }
+
+
+EXPORT_C void RPipe::NotifyDataAvailable(TRequestStatus& aStatus)
+/**
+This method registers the request status object to be completed when data become
+available in the pipe.
+
+@param aStatus Status request that will complete when Data is available.
+
+@return KErrNone Successfully registered.
+ KErrAccessDenied Am attempt has been made to register a space available
+ notification on a handle that has not been opened for
+ reading.
+ KErrCompletion The request was NOT registered as the condition succeeded before wait.
+ KErrBadHandle The handle is not yet associated with a kernel pipe
+ otherwise of the other system wide error code.
+
+
+*/
+ {
+ TInt err = KErrNone;
+ if(!iHandle)
+ {
+ err = KErrBadHandle;
+ }
+ else if(iHandleType != EReadChannel)
+ {
+ err = KErrAccessDenied;
+ }
+ if(err!= KErrNone)
+ {
+ ReqComplete(aStatus, err);
+ return;
+ }
+ aStatus = KRequestPending;
+ DoRequest(EDataAvailable, aStatus);
+ }
+
+
+
+
+EXPORT_C void RPipe::NotifySpaceAvailable(TInt aSize, TRequestStatus& aStatus)
+/**
+This method registers the request status object to be completed when at least
+aSize bytes are available for writing data into the pipe.
+
+@param aSize Amount of space to wait for in the pipe.
+@param aStatus Status request that will complete when aSize
+ bytes become available.
+
+@returns KErrNone Successfully registered.
+ KErrAccessDenied An attempt has been made to register a space
+ available notification on a handle that has
+ not been opened for writing.
+ KErrArgument If the size is negative, zero, or greater than maximum pipe size
+ KErrBadHandle The handle is not yet associated with a kernel pipe
+ otherwise one of the other system wide error code
+
+
+*/
+ {
+
+ TInt err = KErrNone;
+ if(!iHandle)
+ {
+ err = KErrBadHandle;
+ }
+ else if(iHandleType == EReadChannel)
+ {
+ err = KErrAccessDenied;
+ }
+ else if(aSize <= 0 || aSize > MaxSize())
+ {
+ err = KErrArgument;
+ }
+
+ if(err!= KErrNone)
+ {
+ ReqComplete(aStatus, err);
+ return;
+ }
+ aStatus = KRequestPending;
+ DoRequest(ESpaceAvailable, aStatus, (TAny*)&aSize);
+ }
+
+
+
+
+EXPORT_C TInt RPipe::CancelSpaceAvailable()
+/**
+Cancels an outstanding space available notifier request.
+
+@param None
+
+@returns KErrNone Successfully cancelled the SpaceAvailable request.
+ KErrBadHandle An attempt has been made to Cancel Data Available with a
+ handle which has not been associated with any kernel pipe.
+ KErrAccessDenied An attempt has been made to cancel a space available
+ notification on a handle that has been opened for reading.
+ other wise on of the other system wide error code.
+*/
+ {
+ if(!iHandle)
+ return KErrBadHandle;
+
+ if(iHandleType != EWriteChannel)
+ return KErrAccessDenied;
+
+ DoCancel(ECancelSpaceAvailable);
+
+ return KErrNone;
+ }
+
+
+
+EXPORT_C TInt RPipe::CancelDataAvailable()
+/**
+Cancels an outstanding data available notifier request.
+
+@param None
+@return KErrNone Successfully cancelled the DataAvailable request.
+ KErrBadHandle An attempt has been made to Cancel Data Available with a
+ handle which has not been associated with any kernel pipe.
+ KErrAccessDenied Am attempt has been made to cancel a data available
+ notification on a handle that has been opened for writing.
+ otherwise one of the other system wide error code
+*/
+ {
+ if(!iHandle)
+ return KErrBadHandle;
+
+ if(iHandleType != EReadChannel)
+ return KErrAccessDenied;
+
+ DoCancel(ECancelDataAvailable);
+
+ return KErrNone;
+ }
+
+
+EXPORT_C void RPipe::Flush()
+/**
+This method will empty the pipe of all data
+
+@param None
+@returns None
+*/
+ {
+ DoControl(EFlushPipe);
+ }
+
+
+EXPORT_C TInt RPipe::HandleType()const
+/**
+This method returns the Type of operation it can perform with the current handle.
+@param None
+@returns
+ EReadChannel If the current handle is associated to the kernel-side
+ pipe object as to perform Read operations.
+ EWriteChannel If the current handle is associated to the kernel-side
+ pipe object as to perform Write operations.
+ KErrBadHandle If the handle is not associated with Kernel-side object.
+ otherwise one of the other system wide error code
+*/
+ {
+ if(!iHandle)
+ return KErrBadHandle;
+ else
+ return iHandleType;
+ }
+
+
+EXPORT_C TInt RPipe::Size()
+/**
+Returns the available data in the pipe
+@param None
+@return >= 0 Amount of data available in the pipe
+ KErrBadHandle The handle is not yet opened
+ otherwise one of the other system wide error code.
+
+*/
+ {
+ if(!iHandle)
+ return KErrBadHandle;
+
+ return DoControl(EDataAvailableCount);
+ }
+
+
+TInt RPipe::PipeHandle()const
+/**
+Returns the id of Pipe it has created.
+*/
+ {
+ return iPipeHandle;
+ }
+
+
+void RPipe::ReqComplete(TRequestStatus& aStatus, TInt err)
+ {
+ TRequestStatus* req=(&aStatus);
+ User::RequestComplete(req,err);
+ }
+
+EXPORT_C void RPipe::WaitForReader(const TDesC& aName, TRequestStatus& aStatus)
+/**
+Block the thread until the other end of the pipe is opened for reading. If the other end
+is already opened for reading the call will not block and status will complete immediately.
+
+Please note that WaitForReader API will open a valid Write End of the pipe if not opened already.
+User need not open write end of the pipe again after WaitForReader call.
+
+@param aName Name of the kernel-side pipe object to wait for
+@param aStatus Status request that will complete when the other end is opened
+ for reading.
+
+@return KErrNone Request is successfully registered
+ KErrBadName If the length of aName is greater then KMaxFileName or NULL
+ KErrInUse A notifier of this type has already been registered.
+ KErrPermissionDenied Not sufficient capabiliites
+ KErrAccessDenied WaitForReader request is issued using Read handle.
+ otherwise one of the other system wide error code.
+*/
+ {
+ // To wait for Reader end pass flag as EWaitForReader.
+ TInt aFlag = EWaitForReader;
+ Wait(aName, aStatus , aFlag );
+ }
+
+EXPORT_C void RPipe::WaitForWriter(const TDesC& aName, TRequestStatus& aStatus)
+/**
+Block the thread until the other end of the pipe is opened for writing. If the other end
+is already opened for writing the call will not block and status will complete immediately
+
+Please note that WaitForWriter API will open a valid Read End of the pipe if not opened already.
+User need not open read end of the pipe again after WaitForWriter call.
+
+@param aName Name of the kernel-side pipe object to wait for
+@param aStatus Status request that will complete when the other end is opened
+ for writing.
+
+@return KErrNone Request is successfully registered
+ KErrBadName If the length of aName is greater then KMaxFileName or NULL
+ KErrInUse A notifier of this type has already been registered.
+ KErrPermissionDenied Not sufficient capabiliites
+ KErrAccessDenied WaitForWriter request is issued using Write handle.
+ otherwise one of the other system wide error code.
+*/
+ {
+ // To wait for Writer end pass flag as EWaitForWriter.
+ TInt aFlag = EWaitForWriter;
+ Wait(aName, aStatus , aFlag );
+ }
+
+
+void RPipe::Wait(const TDesC& aName, TRequestStatus& aStatus , TInt aChoice)
+/**
+Block the thread until the other end of the pipe is opened for reading (or writing). If the other end
+is already opened for reading (or writing) the call will not block and status will complete immediately.
+
+
+
+@param aName Name of the kernel-side pipe object to wait for
+@param aStatus Status request that will complete when the other end is opened
+ for reading (or Writing).
+@param aChoice EWaitForReader for WaitForReader.
+ EWaitForWriter for WaitForWriter.
+
+@return KErrNone Request is successfully registered
+ KErrBadName If the length of aName is greater then KMaxFileName or NULL
+ KErrInUse A notifier of this type has already been registered.
+ KErrPermissionDenied Not sufficient capabiliites
+ KErrAccessDenied WaitForReader request is issued using Read handle or
+ WaitForWriter request is issued using Write handle.
+ otherwise one of the other system wide error code.
+*/
+ {
+
+ // Code to check a valid Name field as per Symbian naming convention
+ TInt err = User::ValidateName(aName);
+ if(err != KErrNone)
+ {
+ ReqComplete(aStatus, err);
+ return;
+ }
+
+ if((aName.Length() > KMaxKernelName) || (aName.Length() == 0))
+ {
+ ReqComplete(aStatus, KErrBadName);
+ return;
+ }
+
+ TBuf8<KMaxKernelName> name8;
+ name8.Copy(aName);
+
+ aStatus = KRequestPending;
+ // Check if the current instance of RPipe is already opened.
+ if (!iHandle)
+ {
+ // Perform the capability check and create the channel
+ err = DoCreate(Name(),VersionRequired(), KNullUnit, NULL, NULL);
+ if (err!= KErrNone)
+ {
+ ReqComplete(aStatus, err);
+ return;
+ }
+
+ if (aChoice == EWaitForReader)
+ {
+ // Open the Write handle.
+ err = DoControl(EOpenToWriteNamedPipe, (TAny*)&name8);
+ if(err == KErrNone)
+ {
+ iSize = DoControl(ESize);
+ iHandleType = EWriteChannel;
+ }
+ }
+ else
+ {
+ // Open the Read handle.
+ err = DoControl(EOpenToReadNamedPipe, (TAny*)&name8);
+ if(err == KErrNone)
+ {
+ iSize = DoControl(ESize);
+ iHandleType = EReadChannel;
+ }
+ }
+
+ if ( err!= KErrNone)
+ {
+ Close();
+ ReqComplete(aStatus, err);
+ return;
+ }
+ }
+ // use the existing Logical channel to send the request.
+ DoRequest(EWaitNotification, aStatus, (TAny*)&name8,(TAny*)&aChoice);
+ }
+
+