kernel/eka/kernel/sipc.cpp
changeset 36 538db54a451d
parent 31 56f325a607ea
child 90 947f0dc9f7a8
child 198 2bb754abd467
--- a/kernel/eka/kernel/sipc.cpp	Tue Jan 19 13:48:03 2010 +0000
+++ b/kernel/eka/kernel/sipc.cpp	Mon Jan 18 21:31:10 2010 +0200
@@ -546,6 +546,8 @@
 	NKern::ThreadEnterCS();
 	NKern::UnlockSystem();
 	TInt r = KErrNone;
+	TBool anyPins = EFalse;
+	TPinArray pinArray = { { 0, 0, 0, 0 } };			// local, copy to heap later if used
 
 	for (TInt i = 0; descFlags != 0; ++i, argPinFlags >>= 1, descFlags >>= TIpcArgs::KBitsPerType)
  		{
@@ -561,19 +563,11 @@
 			TUint pinLength = desInfo.IsWriteable() ? desInfo.MaxLength() : desInfo.Length();
 			if (pinLength)
 				{
-				if (!iPinArray)
-					{
-					iPinArray = new TPinArray;
-					if (!iPinArray)
-						{
-						r = KErrNoMemory;
-						break;
-						}
-					}
-
 				// This will only create and pin if the descriptor data is paged.
 				// An out-of-memory error here means we fail the whole operation.
-				r = Kern::CreateAndPinVirtualMemory(iPinArray->iPinPtrs[i], desInfo.DataPtr(), pinLength);
+				r = Kern::CreateAndPinVirtualMemory(pinArray.iPinPtrs[i], desInfo.DataPtr(), pinLength);
+				if (pinArray.iPinPtrs[i])
+					anyPins = ETrue;
 				if (r == KErrNoMemory)
 					break;
 				if (r != KErrNone)
@@ -589,24 +583,27 @@
 			}
 		}
 
+	if (anyPins && r != KErrNoMemory)
+		{
+		iPinArray = new TPinArray (pinArray);
+		if (!iPinArray)
+			r = KErrNoMemory;
+		}
+
 	if (r == KErrNoMemory)
 		{
 		// Failed to pin everything so clean up any pin objects created.
 		// This will also unpin any pinned memory.
-		if (iPinArray)
-			{
-			UnpinMessageArguments(iPinArray);
-			delete iPinArray;
-			iPinArray = NULL;
-			}
+		UnpinMessageArguments(&pinArray);
 		}
 
 	NKern::LockSystem();
 
 	// Remove the access on the session.
 	if (aSession->TotalAccessDec() == DObject::EObjectDeleted)
-		{// This was the last access on the session and it has been deleted so 
-		// don't access any of its members.
+		{
+		// This was the last access on the session and it has been deleted
+		// so don't access any of its members.
 		r = KErrDisconnected;
 		}
 	NKern::ThreadLeaveCS();