kernel/eka/euser/rpipe.cpp
changeset 0 a41df078684a
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     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