os/kernelhwsrv/kernel/eka/euser/rpipe.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2006-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 //
    15 
    16 /**
    17  @file rpipe.cpp
    18  @internalTechnology
    19 */
    20 
    21 #include <e32def.h>
    22 #include <e32def_private.h>
    23 #include "rpipe.h"
    24 
    25 EXPORT_C TInt RPipe::Init()
    26 /**
    27 Static method to load the pipe device driver.  
    28 
    29 @param None
    30 
    31 @return KErrNone	If the pipe is successfully loaded, otherwise one of the 
    32 					system wide error code.
    33 */
    34 	{
    35 	_LIT(KDriverLddFileName,"PIPELIB");
    36 	return User::LoadLogicalDevice(KDriverLddFileName);
    37 	}
    38 
    39 
    40 EXPORT_C  TInt RPipe::Create( TInt aSize, RPipe& aReader, RPipe& aWriter, TOwnerType aTypeR, TOwnerType aTypeW)
    41 /**
    42 Static method to create a new, unnamed pipe. 
    43 By default, any thread in the process can use the handle to access the Pipe. However, 
    44 specifying EOwnerThread as the second and fourth parameter to this function, means 
    45 that only the creating thread can use this  handle to access the Pipe.
    46 
    47 @param	aReader			Handle to the read end of the pipe. If the call is successful, 
    48 						this handle will be opened for reading.
    49 @param aWriter			Handle to the write end of the pipe. If the call is successful, 
    50 						this handle will be opened for writing.
    51 @param aTypeR, aTypeW	The type of the ownership of the handle to be created for the 
    52 						read and write
    53 @param aSize			Size of the pipe to be created, in bytes.
    54 
    55 @return KErrNone				Pipe successfully created and the read and write handles opened,
    56 		KErrOverflow			Maximum number of pipes has been reached.
    57 		KErrNoMemory			Insufficient memory to create pipe
    58 		KErrArgument			If the specified size is negative or zero
    59 		KErrInUse				The current handle has already been opened.
    60 								otherwise one of the other system wide error codes
    61 */
    62 
    63 	{
    64  	TInt err = aReader.Create(aSize, aTypeR);
    65 	if (err != KErrNone )
    66 		return err;
    67 	else
    68 		{
    69 		err = aWriter.Open(aReader, aTypeW);	
    70 		if(err!= KErrNone)
    71 			aReader.Close();
    72 		}
    73 	return err;
    74 	}
    75 
    76 TInt RPipe::Create(TInt aSize, TOwnerType aType)
    77 /**
    78 Creates a Kernel side pipe and opens a handle for reading.
    79 By default any thread in the process can use the handle to access to Read the Pipe. 
    80 However, specifying EOwnerThread as the second parameter to this function, means 
    81 that only the creating thread can use this handle to access the pipe.
    82 
    83 @param	aSize			Size of the  pipe to create, in bytes.
    84 
    85 @param	aType			The type of the handle to be created for the reading 
    86 						end of the pipe
    87 
    88 @return KErrNone				Pipe successfully created and handle opened for reading, 
    89 		 KErrInUse				The current handle has already been opened.
    90 		 KErrOverflow	      	Maximum number of pipes has been reached.
    91 		 KErrNoMemory			Insufficient memory to create pipe
    92 	 	 KErrArgument			If the specified size is negative or zero
    93 								otherwise one of the other system wide error code
    94 */
    95 	{
    96 
    97 	// Check if the current handle is already opened for reading/writing
    98 	if ( iHandle && HandleType())
    99 		return KErrInUse;
   100 	
   101 	if(aSize <= 0 )
   102 		return KErrArgument;
   103 	
   104 	// Perform the capability check and create the channel
   105 	TInt err = DoCreate(Name(), VersionRequired(), KNullUnit, NULL, NULL, aType, ETrue);
   106 	if (err!= KErrNone)	
   107 			return err;
   108 	
   109 	// Create an un-named pipe with the specified size 
   110 	err = DoControl(ECreateUnNamedPipe, (TAny*)&aSize);
   111 	if (err>0)
   112 		{
   113 		iSize = DoControl(ESize);
   114 		iHandleType = EReadChannel;
   115 		iPipeHandle = err;
   116 		err = KErrNone;
   117 		}
   118 	else
   119 		{
   120 		Close();
   121 		}
   122 	return err;
   123 	}
   124 
   125 
   126 EXPORT_C TInt RPipe::Open(RMessagePtr2 aMessage, TInt aParam, TOwnerType aType)
   127 /**
   128 Opens a handle to pipe using a handle number sent by a client to a server.
   129 This function is called by the server.
   130 
   131 @param	aMessage		The message pointer. 
   132 
   133 @param	aParam			An index specifying which of the four message arguments contains the handle number. 
   134 
   135 @param	aType			An enumeration whose enumerators define the ownership of this logical channel handle. 
   136 						If not explicitly specified, EOwnerProcess is taken as default.
   137 @return	KErrNone		if successful; 
   138 		KErrArgument	if the value of aParam is outside the range 0-3; 
   139 		KErrBadHandle	if not a valid handle; 
   140 						otherwise one of the other system-wide error codes. 
   141 
   142 
   143 */
   144 	{
   145 	TInt err = RBusLogicalChannel::Open(aMessage, aParam,  aType);
   146 	if (err)
   147 		{
   148 		return err;
   149 		}
   150 	err = DoControl(RPipe::EGetPipeInfo,&iHandleType,&iSize);
   151 	return err;	
   152 
   153 	}
   154 	
   155 
   156 EXPORT_C TInt RPipe::Open(TInt aArgumentIndex, TOwnerType aType)
   157 /**
   158 Opens the handle to pipe which is passed by a process to child process using 
   159 RProcess.SetParameter function call. Pipe handle type remains same(i.e. if read handle is passed 
   160 by process then read handle will be open).
   161 
   162 @param	aArgumentIndex	An index that identifies the slot in the process environment 
   163 						data that contains the handle number. This is a value relative 
   164 						to zero, i.e. 0 is the first item/slot. This can range from 0 to 15.
   165 
   166 @param	aType			The type of the handle to be created for the read/write end
   167 
   168 @return	KErrNone		Pipe successfully created, 
   169 						otherwise of the other system wide error code.
   170 */
   171 	{
   172 	
   173 	TInt err = RBusLogicalChannel::Open(aArgumentIndex,aType);
   174 	if (err)
   175 		{
   176 		return err;
   177 		}
   178 	err = DoControl(RPipe::EGetPipeInfo,&iHandleType,&iSize);
   179 	return err;
   180 	}
   181 
   182 TInt RPipe::Open(const RPipe& aReader, TOwnerType aType)
   183 /**
   184 Opens a handle to write to a pipe. The pipe must have been created previously. 
   185 By default any thread in the process can use the handle to access to write to 
   186 the pipe. However, specifying EOwnerThread as the second parameter to this function, 
   187 means that only the opening thread can use this handle to write to the pipe.
   188 
   189 @param	aReader		Handle to the reading end of the pipe.
   190 
   191 @param	aType		The type of the handle to be created for the write end
   192 
   193 @return	KErrNone				Pipe successfully created, 
   194 			KErrInUse			The current handle has already been opened
   195 			KErrAccessDenied	The read handle is not open for reading
   196 								otherwise of the other system wide error code.
   197 */
   198 	{
   199 	// Check if the current handle is already opened for reading/writing
   200 	if ( iHandle && HandleType())
   201 		return KErrInUse;
   202 	
   203 	// Check the read handle 
   204 
   205 	if (aReader.HandleType() != EReadChannel) 
   206 		return KErrAccessDenied;
   207 	
   208 	// Perform the capability check and create the channel
   209 	TInt err = DoCreate(Name(),VersionRequired(), KNullUnit, NULL, NULL, aType, ETrue);
   210 	if (err!= KErrNone)
   211 		return err;
   212 	
   213 	// Obtained the handle number
   214 	TInt id = aReader.PipeHandle();
   215 	
   216 
   217 	// Set the Write channel 
   218 	err = DoControl(EOpenUnNamedPipe,(TAny*)&id);
   219 	
   220 	if( err == KErrNone)
   221 		{
   222 		iSize = DoControl(ESize);
   223 		iHandleType  = EWriteChannel;
   224 		iPipeHandle = id;	
   225 		
   226 		}
   227 	else
   228 		{
   229 		Close();
   230 		}
   231 		
   232 		
   233 	return err;
   234 	}
   235 
   236 
   237 // Methods to Support Named Pipe
   238 
   239 EXPORT_C TInt RPipe::Define(const TDesC& aName, TInt aSize)
   240 /**
   241 Static method to create a new, named pipe of a given size. Calling this method 
   242 will create a new kernel object only. No user-side handles are created or opened.
   243 
   244 @param	aName		Name to be assigned to the Kernel-side pipe object.
   245 @param	aSize		Size of the pipe to create, in bytes.
   246 
   247 @return KErrNone					Pipe successfully created.
   248 		 KErrBadName				If the length of aName is greater than KMaxFileName
   249 									or Null
   250 		 KErrOverflow				Maximum number of pipes has been reached
   251 		 KErrNoMemory				Insufficient memory to create pipe.
   252 		 KErrArgument				if Size is negative
   253 		 KErrAlreadyExist			If a pipe with the specified name already exist.
   254 		 							otherwise one of the other system wide error code.
   255 */
   256 	{
   257 	// Code to check a valid Name field as per Symbian naming convention
   258 	TInt err = User::ValidateName(aName);
   259 	if(KErrNone!=err)
   260 		return err;  
   261 	
   262 	if((aName.Length() > KMaxKernelName) || (aName.Length() == 0))
   263 		return KErrBadName;
   264 	
   265 	if(aSize <= 0)
   266 		return KErrArgument;
   267 	
   268 	// Perform the capability check and create the channel
   269 	RPipe temp;
   270  	err = temp.DoCreate(Name(),VersionRequired(), KNullUnit, NULL, NULL);
   271 	if (err!= KErrNone)
   272 		return err;
   273 	
   274 		// Define
   275 	TPipeInfoBuf aInfo;
   276 	aInfo().isize = aSize;
   277 	aInfo().iName.Copy(aName);
   278 	
   279 	// Define the Named pipe 
   280 	err = temp.DoControl(EDefineNamedPipe, (TAny*)&aInfo);
   281 	temp.Close();	
   282 	return err;
   283 
   284 	}
   285 	
   286 
   287 EXPORT_C TInt RPipe::Define( const  TDesC& aName, TInt aSize, const TSecurityPolicy& aPolicy)
   288 /**
   289 Static method to create a new, named pipe of a given size. Calling this method 
   290 will create a new kernel object only. No user-side handles are created or opened.
   291 
   292 @param	aName		Name to be assigned to the Kernel-side pipe object.
   293 @param	aSize		Size of the pipe to create, in bytes.
   294 
   295 @return KErrNone					Pipe successfully created.
   296 		 KErrBadName				If the length of aName is greater than KMaxFileName
   297 									or Null
   298 		 KErrOverflow				Maximum number of pipes has been reached
   299 		 KErrNoMemory				Insufficient memory to create pipe.
   300 		 KErrArgument				if Size is negative
   301 		 KErrPermissionDenied		Not sufficient capabiliites
   302 		 KErrAlreadyExist			If a pipe with the specified name already exist.
   303 		 							otherwise one of the other system wide error code.
   304 */
   305 	{
   306 	
   307 	// Code to check a valid Name field as per Symbian naming convention
   308 	TInt err = User::ValidateName(aName);
   309 	if(KErrNone!=err)
   310 		return err;  
   311 	
   312 	if((aName.Length() > KMaxKernelName) || (aName.Length() == 0))
   313 		return KErrBadName;
   314 	
   315 	if(aSize <= 0)
   316 		return KErrArgument;
   317 	
   318 	// Perform the capability check and create the channel
   319 	RPipe temp;
   320  	err = temp.DoCreate(Name(),VersionRequired(), KNullUnit, NULL, NULL);
   321 	if (err!= KErrNone)
   322 		return err;
   323 	
   324 	// Define
   325 	TPipeInfoBuf aInfo;
   326 	aInfo().isize = aSize;
   327 	aInfo().iName.Copy(aName);
   328 	err = temp.DoControl(EDefineNamedPipe, (TAny*)&aInfo, (TAny*)&aPolicy);
   329 	temp.Close();
   330 		
   331 	return err;
   332 	
   333 	
   334 	}
   335 	
   336 		
   337 
   338 EXPORT_C  TInt RPipe::Destroy( const TDesC& aName)
   339 /**
   340 Static method to destroy a previously created named pipe. Any data not read from 
   341 the pipe will be discarded. This method will fail if there is any handles still 
   342 open on the pipe or the calling thread as insufficient capabilities.
   343 
   344 @param	aName		Name of the Kernel-side pipe object to destroy
   345 		
   346 @return  KErrNone					Pipe successfully destroyed
   347 		 KErrInUse					The pipe still has one or more handle open to it
   348 		 KErrPermissionDenied		Not sufficient capabiliites
   349 		 KErrNotFound				If no kernel pipe exist with the specified name
   350 		 							otherwise one of the other system wide error code.
   351 */
   352 	{
   353 	// Code to check a valid Name field as per Symbian naming convention
   354 	TInt err = User::ValidateName(aName);
   355 	if(KErrNone!=err)
   356 		return err;  
   357 	
   358 	if((aName.Length() > KMaxKernelName) || (aName.Length() == 0))
   359 		return KErrBadName;
   360 	
   361 	// Perform the capability check and create the channel
   362 	RPipe temp;
   363  	err = temp.DoCreate(Name(),VersionRequired(), KNullUnit, NULL, NULL);
   364 	if (err!= KErrNone)
   365 		return err;
   366 	
   367 	TBuf8<KMaxKernelName> name;
   368 	name.Copy(aName);
   369 	
   370 	// Destroy 
   371 	err = temp.DoControl(EDestroyNamedPipe, (TAny*)&name, NULL);
   372 	temp.Close();
   373 		
   374 	return err;
   375 
   376 	}
   377 
   378 
   379 EXPORT_C TInt RPipe::Open(const TDesC& aName, TMode aMode)
   380 /**
   381 Opens the pipe for the access mode specified. If the handle is opened to read or Write. 
   382 The handle is opened regardless of whether or not there is a open handle at the other end.
   383 
   384 If the handle is opened as " Write but Fail On No Readers" the call will fail unless there 
   385 is atleast one handle open for reading at the other end.
   386 
   387 @param		aName		Name of the kernel-side pipe object to destroy
   388 @param		aMode		Access mode for the handle.
   389 
   390 @return 	KErrNone				Handle successfully opened.
   391 			KErrBadName				If the length of aName is greater than KMaxFileName or Null
   392 			KErrInUse				The pipe still has one or more handle open to it.
   393 			KErrPermissionDenied	Not sufficient capabiliites
   394 			KErrNotFond				If there is no kernel instance with the specified name
   395 			KErrNotReady			Open Fails when no Readers is available while opening
   396 									With TMode = EOpenToWriteButFailOnNoReaders
   397 									otherwise one of the other system wide error code.
   398 									
   399 */
   400 	{
   401 
   402 	// Check if the current handle is already opened for reading/writing
   403 	if ( iHandle && HandleType())
   404 		return KErrInUse;	
   405 	
   406 	TInt err = User::ValidateName(aName);
   407 	if(KErrNone!=err)
   408 		return err; 
   409 	
   410 	if((aName.Length() > KMaxKernelName) || (aName.Length() == 0))
   411 		return KErrBadName;
   412 	
   413 	// Perform the capability check and create the channel
   414 	err = DoCreate(Name(),VersionRequired(), KNullUnit, NULL, NULL);
   415 	if (err!= KErrNone)
   416 		return err;
   417 	
   418 	TBuf8<KMaxKernelName> name;
   419 	name.Copy(aName);
   420 
   421 
   422     if (aMode == EOpenToRead)
   423     	{
   424  		err = DoControl(EOpenToReadNamedPipe,(TAny*)&name);
   425 		if(err == KErrNone)
   426 			{
   427 			iSize = DoControl(ESize);
   428 			iHandleType = EReadChannel;		
   429 			}
   430 		else 
   431 			Close();
   432  		}
   433  	else if(aMode == EOpenToWrite)
   434  		{
   435  		err = DoControl(EOpenToWriteNamedPipe, (TAny*)&name);
   436 		if(err == KErrNone)
   437 			{
   438 			iSize = DoControl(ESize);
   439 			iHandleType = EWriteChannel;			 			
   440 			}
   441 		else
   442 			Close();
   443  	}
   444  	else if (aMode == EOpenToWriteNamedPipeButFailOnNoReaders)
   445  		{
   446  		err = DoControl(EOpenToWriteButFailOnNoReaderNamedPipe, (TAny*)&name);
   447 		if(err == KErrNone)
   448 			{
   449 			iSize = DoControl(ESize);
   450 			iHandleType = EWriteChannel;	
   451 			}
   452 		else
   453 		Close();	
   454  		}
   455  	else
   456  		{	
   457  		Close();	
   458  		err = KErrArgument;
   459  		}
   460 	return err;
   461 	}
   462 
   463 
   464 
   465 EXPORT_C void RPipe::Wait(const TDesC& aName, TRequestStatus& aStatus)
   466 /**
   467 Block the thread until the other end of the pipe is opened for reading. If the other end
   468 is already opened for reading the call will not block and status will complete immediately
   469 This function will be deprecated , use WaitForReader.
   470 Please note that Wait API will open a valid Write End of the pipe if not opened already.
   471 User need not open write end of the pipe again after Wait call.
   472 
   473 
   474 @param	aName			Name of the kernel-side pipe object to wait for 
   475 @param  aStatus			Status request that will complete when the other end is opened
   476 						for reading.
   477 
   478 @return  KErrNone				Request is successfully registered
   479 		 KErrBadName			If the length of aName is greater then KMaxFileName or NULL
   480 		 KErrInUse				A notifier of this type has already been registered.
   481 		 KErrPermissionDenied	Not sufficient capabiliites
   482 		 						otherwise one of the other system wide error code.
   483 */
   484 	{
   485 	// To wait for Reader end pass flag as EWaitForReader.
   486 	TInt aFlag = EWaitForReader;
   487 	Wait(aName, aStatus , aFlag );
   488 	}
   489 
   490 
   491 EXPORT_C  void RPipe::CancelWait()
   492 /**
   493 Cancel previous call to RPipe::Wait(), RPipe::WaitForReader (), RPipe::WaitForWriter ()
   494 
   495 @param	None
   496 @return None
   497 */
   498 	{
   499 	if(!iHandle)
   500 		return;	
   501 	DoCancel(ECancelWaitNotification);
   502 	}
   503 
   504 
   505 
   506 // Generic Methods
   507 
   508 EXPORT_C void RPipe::Close()
   509 /**
   510 Close the handle. This method exhibits different behaviour depending upon whether the pipe
   511 is named or unnamed.
   512 Named pipes are allowed to persist without any open handles. Closing the last handle on a 
   513 named pipe will not destroy the kernel-side object. For an unnamed pipe, closing the last 
   514 handle will destroy the kernel-side pipe object. Any unread data in the pipe will be 
   515 discarded.
   516 An attempt to close an unnamed pipe will have no effect. Closing a handle will not affect 
   517 the state of any other handles that may be open on the pipe.
   518 
   519 @param		None
   520 
   521 @return		None
   522 */
   523 	{
   524 	if(!iHandle)
   525 		return;
   526 	RHandleBase::Close();
   527 	}
   528 
   529 
   530 
   531 
   532 EXPORT_C TInt RPipe::MaxSize()
   533 /**
   534 Returns the total size, in bytes, of the Pipe
   535 @param		None
   536 
   537 @return 	>= 0				Size of the pipe in bytes
   538 			KErrBadHandle		The handle is not open
   539 								otherwise one of the other system wide error code.
   540 */
   541 	{
   542 	if (!iHandle )
   543 		 return KErrBadHandle;
   544 	
   545 	if(iHandleType == EReadChannel || iHandleType == EWriteChannel)
   546 		return iSize;
   547 	else
   548  		return KErrAccessDenied;
   549 	}
   550 
   551 
   552 
   553 EXPORT_C TInt RPipe::Read(TDes8& aMsg, TInt aNumByte)
   554 /**
   555 This is non-blocking synchronous method to read aNumByte bytes from the pipe into the 
   556 descriptor aMsg and returns the number of bytes read. If the pipe is empty the call will
   557 immediately return a value of zero to indicate that no data was read
   558 
   559 A successful RPipe::Read() operation will free up more space in the pipe.
   560 
   561 @param	aMsg		Descriptor to receive data
   562 @param	aNumByte	Number of bytes to be received.
   563 
   564 @return 	>0					Amount of data read from the pipe, in bytes.
   565 			KErrUnderFlow		The pipe was empty, no data was read
   566 			KErrAccessDenied	An attempt has been made to read from a handle 
   567 								has been opened for writing.
   568 			KErrBadHandle		An attempt has been made to read from a handle
   569 								that has not been opened.
   570 			KErrNotReady	    Write end is closed and Pipe is empty.
   571 			0					No Data is available
   572 								otherwise one of the other system wide error code.
   573 */
   574 	{
   575 	// Check for the error condition
   576 	if (!iHandle)
   577 		return KErrBadHandle;
   578 	
   579 	// Check for KErrArgument
   580 	if(aNumByte > aMsg.MaxLength())
   581 		return KErrArgument;
   582 
   583 	if(iHandleType != EReadChannel)
   584 		return KErrAccessDenied;
   585 
   586 	return DoControl(ERead, (TAny*)&aMsg, (TAny*)&aNumByte);
   587 	}
   588 
   589 
   590 
   591 
   592 EXPORT_C TInt RPipe::Write( const TDesC8& aData, TInt aNumByte)
   593 /**
   594 This is non-blocking synchronous method to write data from aData. If the pipe is 
   595 full it will return immediately with KErrOverFlow
   596 
   597 @param	 aData			Descriptor from which data has to be written to the pipe
   598 
   599 @return	>0					Amount of data written to the pipe, in bytes
   600 		KErrAccessDenied	An attempt has been made to write to a handle that
   601 							has been opened for reading.
   602 		KErrArgument		If the size is more then aData's length
   603 		KErrBadName
   604 		KErrOverFlow		The pipe is full. No data was inserted into the pipe.
   605 		KErrBadHandle		An attempt has been made to read from a handle that
   606 							has not been opened.
   607 		KErrCompletion		If the specified size is greater then the available size.
   608 		KErrNotReady	    Read end is closed.
   609 							otherwise one of the other system wide error code.
   610 	
   611 */
   612 	{
   613 	// Check for the error condition
   614 	if (!iHandle)
   615 		return KErrBadHandle;
   616 	
   617 	// Check for KErrArgument
   618 	if(aNumByte > aData.Length())
   619 		return KErrArgument;
   620 	
   621 	if(iHandleType == EReadChannel)
   622 		return KErrAccessDenied;
   623 
   624 	return DoControl(EWrite, (TAny*)&aData, (TAny*)&aNumByte);
   625 
   626 	}
   627 
   628 
   629 EXPORT_C TInt RPipe::ReadBlocking( TDes8& aMsg, TInt aNumByte)
   630 /**
   631 This is synchronous, blocking read operation. If the pipe is empty the client thread will 
   632 be blocked until data become available. A successful RPipe::ReadBlocking() operation will
   633 free up more space in the pipe. This method is accompanied by data notification method to
   634 complete the blocking mechanism
   635 
   636 @param		aMsg		Descriptor to receive data
   637 @param		aNumByte	Number of bytes to be received
   638 
   639 @return 	>0					Amount of data read from the pipe in bytes.
   640 			KErrAccessDenied	Am attempt has been made to read from the handle that
   641 								has been opened for writing.
   642 			KErrBadHandle		Am attempt has been made to read from a handle that has
   643 								not been opened.
   644 			KErrArgument 		if the size is negative.
   645 			KErrInUse			If the call is active from some another thread.
   646 			KErrNotReady	    Write end is closed and Pipe is empty.
   647 								otherwise one of the system wide error code.
   648 */
   649 	{
   650 
   651 	TRequestStatus stat = KRequestPending;
   652  	TInt err = KErrNone;
   653  	
   654 	// Check for the error condition
   655 	if (!iHandle)
   656 		return KErrBadHandle;
   657 	
   658 	if(aNumByte <= 0)
   659 		return KErrArgument;
   660 
   661 	if(iHandleType != EReadChannel)
   662 		return KErrAccessDenied;
   663 
   664 	// Asynchronous request to notify the data available.
   665 	do 
   666 		{
   667 	 	stat = KRequestPending;
   668 		DoRequest(EReadBlocking, stat);
   669 		User::WaitForRequest(stat);
   670 		err = stat.Int();
   671 		if (err == KErrInUse || err == KErrNotReady)
   672 			{
   673 			return err;
   674 			}
   675 			
   676 		// Synchronous read operation
   677 	 	err = DoControl(ERead, (TAny*)&aMsg, (TAny*)&aNumByte); 
   678 	 	if (err == KErrNotReady)
   679 	 		return err;
   680 	 	
   681 	 	} while (err == 0);
   682 	
   683  	return err;	
   684 	}
   685 
   686 
   687 
   688 EXPORT_C  TInt RPipe::WriteBlocking(const TDesC8& aData, TInt aNumByte)
   689 /**
   690 This is a synchronous, blocking write operation. It will attempt to
   691 write aNumByte's worth of data to the pipe, waiting till space is available.
   692 If aNumByte is less than or equal to the pipe size, MaxSize(), the write
   693 shall be atomic (w.r.t other threads sharing this channel), otherwise
   694 the data will be split into multiple atomic writes of pipe size
   695 (except, of course, if less than MaxSize bytes of data remain to be written).
   696 
   697 @param		aData		Descriptor from which data has to be written to the pipe.
   698 @param      aNumByte	Amount of data to be written to the pipe
   699 
   700 @return 	>0					Amount of data written to the pipe, in bytes.
   701 			KErrAccessDenied	An attempt has been made to write to a handle that
   702 								has been opened for reading.
   703 			KErrBadHandle		An attempt has been made to read from a handle that has
   704 								not been open.
   705 			KErrArgument 		if the size is negative.
   706 			KErrNotReady	    Read end is closed.
   707 								otherwise one of the other system wide error code.
   708 */				
   709 	{
   710 	TBool first = ETrue;
   711 	TRequestStatus stat = KRequestPending;
   712  	TInt err = 0;
   713  	TInt index = 0;
   714  	TInt writeindex =0;
   715  	TPtrC8 tmp;
   716 	TInt r = aNumByte;
   717 
   718 	// Check for the error condition
   719 	if (!iHandle)
   720 		return KErrBadHandle;
   721 	
   722 	
   723 	if(aNumByte <= 0)
   724 		return KErrArgument;
   725 	
   726 	
   727 	if(iHandleType == EReadChannel)
   728 		return KErrAccessDenied;
   729 	
   730 	if (aNumByte <= iSize)
   731 		writeindex = aNumByte;
   732 	else 
   733 		writeindex = iSize;
   734 	
   735 	do
   736 		{			
   737 		// Asynchronous request to notify the space available.
   738  		stat = KRequestPending;
   739  		DoRequest(EWriteBlocking, stat,(TAny*)&writeindex);
   740  		User::WaitForRequest(stat);
   741  		err = stat.Int();
   742  		if (err == KErrInUse || err == KErrNotReady) 
   743  			{
   744  			return err;
   745  			}
   746  									
   747 		// Synchronous write operation
   748 		tmp.Set(aData.Ptr()+index, writeindex);
   749  		err = DoControl(EWrite, (TAny*)&tmp, (TAny*)&writeindex); 
   750  		if(err == KErrNotReady)
   751  			{
   752  			return err;
   753  			}
   754 		else
   755 			{
   756 			if ( err == aNumByte)  
   757 				{
   758 				first = EFalse;
   759 				}		
   760 			else
   761 				{
   762 				index  = index + err;
   763 				aNumByte = r - index;
   764 				if(aNumByte < iSize)
   765 					writeindex = aNumByte;
   766 				}
   767 			}	
   768 		}while(first);
   769 		
   770 	return r;	
   771 	}
   772 
   773 
   774 EXPORT_C void RPipe::NotifyDataAvailable(TRequestStatus& aStatus)
   775 /**
   776 This method registers the request status object to be completed when data become
   777 available in the pipe. 
   778 
   779 @param	aStatus			Status request that will complete when Data is available.
   780 
   781 @return KErrNone				Successfully registered.
   782 		KErrAccessDenied		Am attempt has been made to register a space available
   783 								notification on a handle that has not been opened for
   784 								reading.
   785 		KErrCompletion			The request was NOT registered as the condition succeeded before wait.
   786 		KErrBadHandle			The handle is not yet associated with a kernel pipe
   787 								otherwise of the other system wide error code.
   788 
   789 
   790 */
   791 	{
   792 	TInt err = KErrNone;
   793 	if(!iHandle)
   794 		{	
   795 		err = KErrBadHandle;
   796 		}
   797 	else if(iHandleType != EReadChannel)
   798 		{
   799 		err = KErrAccessDenied;
   800 		}
   801 	if(err!= KErrNone)
   802 		{
   803 		ReqComplete(aStatus, err);
   804 		return;
   805 		}
   806 	aStatus = KRequestPending;
   807 	DoRequest(EDataAvailable, aStatus);
   808 	}
   809 
   810 
   811 
   812 
   813 EXPORT_C void RPipe::NotifySpaceAvailable(TInt aSize, TRequestStatus& aStatus)
   814 /**
   815 This method registers the request status object to be completed when at least
   816 aSize bytes are available for writing data into the pipe.
   817 
   818 @param	aSize			Amount of space to wait for in the pipe.
   819 @param	aStatus			Status request that will complete when aSize
   820 						bytes become available.
   821 
   822 @returns KErrNone				Successfully registered.
   823 		 KErrAccessDenied		An attempt has been made to register a space
   824 								available notification on a handle that has
   825 								not been opened for writing.
   826 		 KErrArgument			If the size is negative, zero, or greater than maximum pipe size
   827 		 KErrBadHandle			The handle is not yet associated with a kernel pipe
   828 		 						otherwise one of the other system wide error code
   829 
   830 
   831 */
   832 	{
   833 	
   834 	TInt err = KErrNone;
   835 	if(!iHandle)
   836 		{	
   837 		err = KErrBadHandle;
   838 		}
   839 	else if(iHandleType == EReadChannel)
   840 		{
   841 		err = KErrAccessDenied;
   842 		}
   843 	else if(aSize <= 0 || aSize > MaxSize())
   844 		{
   845 		err = KErrArgument;
   846 		}
   847 		
   848 	if(err!= KErrNone)
   849 		{
   850 		ReqComplete(aStatus, err);
   851 		return;
   852 		}
   853 	aStatus = KRequestPending;
   854 	DoRequest(ESpaceAvailable, aStatus, (TAny*)&aSize);
   855 	}
   856 
   857 
   858 
   859 
   860 EXPORT_C TInt RPipe::CancelSpaceAvailable()
   861 /**
   862 Cancels an outstanding space available notifier request.
   863 
   864 @param		None
   865 
   866 @returns KErrNone			Successfully cancelled the SpaceAvailable request.
   867 		 KErrBadHandle		An attempt has been made to Cancel Data Available with a 
   868 							handle which has not been associated with any kernel pipe.
   869 		 KErrAccessDenied	An attempt has been made to cancel a space available
   870 							notification on a handle that has been opened for reading.
   871 		 					other wise on of the other system wide error code.
   872 */
   873 	{
   874 	if(!iHandle)
   875 		return KErrBadHandle;
   876 	
   877 	if(iHandleType != EWriteChannel)
   878 		return KErrAccessDenied;
   879 	
   880 	DoCancel(ECancelSpaceAvailable);
   881 	
   882 	return KErrNone;
   883 	}
   884 
   885 
   886 
   887 EXPORT_C TInt RPipe::CancelDataAvailable()
   888 /**
   889 Cancels an outstanding data available notifier request.
   890 
   891 @param		None
   892 @return	KErrNone			Successfully cancelled the DataAvailable request.
   893 		KErrBadHandle		An attempt has been made to Cancel Data Available with a 
   894 							handle which has not been associated with any kernel pipe.
   895 		KErrAccessDenied	Am attempt has been made to cancel a data available
   896 							notification on a handle that has been opened for writing.
   897 							otherwise one of the other system wide error code
   898 */
   899 	{
   900 	if(!iHandle)
   901 		return KErrBadHandle;
   902 	
   903 	if(iHandleType != EReadChannel)
   904 		return KErrAccessDenied;
   905 	
   906 	DoCancel(ECancelDataAvailable);
   907 	
   908 	return KErrNone;
   909 	}
   910 
   911 
   912 EXPORT_C void RPipe::Flush()
   913 /**
   914 This method will empty the pipe of all data
   915 
   916 @param	None
   917 @returns None
   918 */
   919 	{
   920 		DoControl(EFlushPipe);
   921 	}
   922 
   923 
   924 EXPORT_C TInt RPipe::HandleType()const 
   925 /**
   926 This method returns the Type of operation it can perform with the current handle.
   927 @param None
   928 @returns 
   929 		EReadChannel	If the current handle is associated to the kernel-side 
   930 						pipe object as to perform Read operations.
   931 		EWriteChannel	If the  current handle is associated to the kernel-side
   932 						pipe object as to perform Write operations.
   933 		KErrBadHandle   If the handle is not associated with Kernel-side object.
   934 						otherwise one of the other system wide error code
   935 */
   936 	{
   937 	if(!iHandle)
   938 		return KErrBadHandle;
   939 	else
   940 		return iHandleType;
   941 	}
   942 
   943 
   944 EXPORT_C TInt RPipe::Size()
   945 /**
   946 Returns the available data in the pipe
   947 @param	None
   948 @return >= 0				Amount of data available in the pipe
   949 		KErrBadHandle		The handle is not yet opened 
   950 							otherwise one of the other system wide error code.
   951 
   952 */
   953 	{
   954 	if(!iHandle)
   955 		return KErrBadHandle;
   956 	
   957 	return DoControl(EDataAvailableCount);	
   958 	}
   959 
   960 
   961 TInt RPipe::PipeHandle()const
   962 /**
   963 Returns the id of Pipe it has created.
   964 */
   965 	{
   966 	return iPipeHandle;
   967 	}
   968 
   969 
   970 void RPipe::ReqComplete(TRequestStatus& aStatus, TInt err)
   971 	{
   972 	TRequestStatus* req=(&aStatus);
   973 	User::RequestComplete(req,err);	
   974 	}
   975 	
   976 EXPORT_C void RPipe::WaitForReader(const TDesC& aName, TRequestStatus& aStatus)
   977 /**
   978 Block the thread until the other end of the pipe is opened for reading. If the other end
   979 is already opened for reading the call will not block and status will complete immediately.
   980 
   981 Please note that WaitForReader API will open a valid Write End of the pipe if not opened already.
   982 User need not open write end of the pipe again after WaitForReader call.
   983 
   984 @param	aName			Name of the kernel-side pipe object to wait for 
   985 @param  aStatus			Status request that will complete when the other end is opened
   986 						for reading.
   987 
   988 @return  KErrNone				Request is successfully registered
   989 		 KErrBadName			If the length of aName is greater then KMaxFileName or NULL
   990 		 KErrInUse				A notifier of this type has already been registered.
   991 		 KErrPermissionDenied	Not sufficient capabiliites
   992 		 KErrAccessDenied		WaitForReader request is issued using Read handle.
   993 		 						otherwise one of the other system wide error code.
   994 */
   995 	{
   996 	// To wait for Reader end pass flag as EWaitForReader.
   997 	TInt aFlag = EWaitForReader;
   998 	Wait(aName, aStatus , aFlag );
   999 	}
  1000 
  1001 EXPORT_C void RPipe::WaitForWriter(const TDesC& aName, TRequestStatus& aStatus)
  1002 /**
  1003 Block the thread until the other end of the pipe is opened for writing. If the other end
  1004 is already opened for writing the call will not block and status will complete immediately
  1005 
  1006 Please note that WaitForWriter API will open a valid Read End of the pipe if not opened already.
  1007 User need not open read end of the pipe again after WaitForWriter call.
  1008 
  1009 @param	aName			Name of the kernel-side pipe object to wait for 
  1010 @param  aStatus			Status request that will complete when the other end is opened
  1011 						for writing.
  1012 
  1013 @return  KErrNone				Request is successfully registered
  1014 		 KErrBadName			If the length of aName is greater then KMaxFileName or NULL
  1015 		 KErrInUse				A notifier of this type has already been registered.
  1016 		 KErrPermissionDenied	Not sufficient capabiliites
  1017 		 KErrAccessDenied		WaitForWriter request is issued using Write handle.
  1018 		 						otherwise one of the other system wide error code.
  1019 */
  1020 	{
  1021 	// To wait for Writer end pass flag as EWaitForWriter.
  1022 	TInt aFlag = EWaitForWriter;
  1023 	Wait(aName, aStatus , aFlag );
  1024 	}
  1025 
  1026 
  1027 void RPipe::Wait(const TDesC& aName, TRequestStatus& aStatus , TInt aChoice)
  1028 /**
  1029 Block the thread until the other end of the pipe is opened for reading (or writing). If the other end
  1030 is already opened for reading (or writing) the call will not block and status will complete immediately.
  1031 
  1032 
  1033 
  1034 @param	aName			Name of the kernel-side pipe object to wait for 
  1035 @param  aStatus			Status request that will complete when the other end is opened
  1036 						for reading (or Writing).
  1037 @param  aChoice			EWaitForReader for WaitForReader.
  1038 						EWaitForWriter for WaitForWriter.
  1039 
  1040 @return  KErrNone				Request is successfully registered
  1041 		 KErrBadName			If the length of aName is greater then KMaxFileName or NULL
  1042 		 KErrInUse				A notifier of this type has already been registered.
  1043 		 KErrPermissionDenied	Not sufficient capabiliites
  1044 		 KErrAccessDenied		WaitForReader request is issued using Read handle or 
  1045 		 						WaitForWriter request is issued using Write handle.	
  1046 		 						otherwise one of the other system wide error code.
  1047 */
  1048 	{
  1049 	
  1050 	// Code to check a valid Name field as per Symbian naming convention
  1051 	TInt err = User::ValidateName(aName);
  1052 	if(err != KErrNone)
  1053 		{
  1054 		ReqComplete(aStatus, err);
  1055 		return;	
  1056 		}
  1057 	
  1058 	if((aName.Length() > KMaxKernelName) || (aName.Length() == 0))
  1059 		{
  1060 		ReqComplete(aStatus, KErrBadName);
  1061 		return;		
  1062 		}
  1063 	
  1064 	TBuf8<KMaxKernelName> name8;
  1065 	name8.Copy(aName);
  1066 	
  1067 	aStatus = KRequestPending;
  1068 	// Check if the current instance of RPipe is already opened.
  1069 	if (!iHandle)
  1070 		{
  1071 		// Perform the capability check and create the channel
  1072 		err = DoCreate(Name(),VersionRequired(), KNullUnit, NULL, NULL);
  1073 		if (err!= KErrNone)
  1074 			{
  1075 			ReqComplete(aStatus, err);
  1076 			return;		
  1077 			}
  1078 		
  1079 		if (aChoice == EWaitForReader) 
  1080 			{
  1081 			// Open the Write handle.
  1082 			err = DoControl(EOpenToWriteNamedPipe, (TAny*)&name8);
  1083 			if(err == KErrNone)
  1084 				{
  1085 				iSize = DoControl(ESize);
  1086 				iHandleType = EWriteChannel;
  1087 				}
  1088 			}
  1089 		else 
  1090 			{
  1091 			// Open the Read handle.
  1092 			err = DoControl(EOpenToReadNamedPipe, (TAny*)&name8);	
  1093 			if(err == KErrNone)
  1094 				{
  1095 				iSize = DoControl(ESize);
  1096 				iHandleType = EReadChannel;
  1097 				}
  1098 			}
  1099 		
  1100 		if ( err!= KErrNone)
  1101 			{
  1102 			Close();
  1103 			ReqComplete(aStatus, err);
  1104 			return;
  1105 			}
  1106 		}		
  1107 	// use the existing Logical channel to send the request.
  1108 	DoRequest(EWaitNotification, aStatus, (TAny*)&name8,(TAny*)&aChoice);
  1109 	}
  1110 
  1111