libraries/memoryaccess/PropertyAccess.cpp
changeset 0 7f656887cf89
equal deleted inserted replaced
-1:000000000000 0:7f656887cf89
       
     1 // PropertyAccess.cpp
       
     2 // 
       
     3 // Copyright (c) 2010 Accenture. All rights reserved.
       
     4 // This component and the accompanying materials are made available
       
     5 // under the terms of the "Eclipse Public License v1.0"
       
     6 // which accompanies this distribution, and is available
       
     7 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 // 
       
     9 // Initial Contributors:
       
    10 // Accenture - Initial contribution
       
    11 //
       
    12 #include <fshell/common.mmh>
       
    13 #include <e32cmn.h>
       
    14 #include <fshell/extrabtrace.h>
       
    15 
       
    16 #include <kernel.h>
       
    17 #include <kern_priv.h>
       
    18 #include "memoryaccess.h"
       
    19 #include "PropertyAccess.h"
       
    20 
       
    21 DPropertyAccess::DPropertyAccess(DThread* aClient)
       
    22 	: iClient(aClient)
       
    23 	{
       
    24 	}
       
    25 
       
    26 TInt DPropertyAccess::HandleProperty(TInt aFunction, TAny* aParams, TAny* aVal)
       
    27 	{
       
    28 	return DoHandleProperty(iClient, aFunction, aParams, aVal);
       
    29 	}
       
    30 
       
    31 TInt DPropertyAccess::DoHandleProperty(DThread* aClient, TInt aFunction, TAny* aParams, TAny* aVal)
       
    32 	{
       
    33 	if (aFunction == RMemoryAccess::EControlPropertyNotify)
       
    34 		{
       
    35 		if (iNotifyClientStatus) return KErrAlreadyExists;
       
    36 		iNotifyClientStatus = (TRequestStatus*)aVal;
       
    37 		iClientNotifyPtr = aParams;
       
    38 		return KErrNone;
       
    39 		}
       
    40 	else if (aFunction == RMemoryAccess::EControlPropertyNotifyCancel)
       
    41 		{
       
    42 		CancelNotifys();
       
    43 		return KErrNone;
       
    44 		}
       
    45 
       
    46 	TInt err;
       
    47 	TProp clientParams;
       
    48 	err = Kern::ThreadRawRead(aClient, aParams, &clientParams, sizeof(TProp));
       
    49 	if (err)
       
    50 		{
       
    51 		return err;
       
    52 		}
       
    53 	//Kern::Printf("HandleProperty %d, iDefine=%d iCat=0x%x iKey=%d", aFunction, clientParams.iDefine, clientParams.iCategory, clientParams.iKey);
       
    54 
       
    55 	NKern::ThreadEnterCS();
       
    56 	RPropertyRef property;
       
    57 	err = property.Open(clientParams.iCategory, clientParams.iKey);
       
    58 	//Kern::Printf("HandleProperty Open ret=%d", err);
       
    59 	if (!err)
       
    60 		{
       
    61 		// Check if it exists but isn't defined (and if it isn't, treat it the same as if it didn't exist)
       
    62 		TPropertyStatus stat;
       
    63 		NKern::LockSystem();
       
    64 		TBool defined = property.GetStatus(stat);
       
    65 		NKern::UnlockSystem();
       
    66 		if (!defined)
       
    67 			{
       
    68 			property.Close();
       
    69 			err = KErrNotFound;
       
    70 			}
       
    71 		}
       
    72 
       
    73 	if (err == KErrNotFound && clientParams.iDefine && (aFunction == RMemoryAccess::EControlSetPropertyDesc || aFunction == RMemoryAccess::EControlSetPropertyInt))
       
    74 		{
       
    75 		err = property.Attach(clientParams.iCategory, clientParams.iKey);
       
    76 		TInt attr = (aFunction == RMemoryAccess::EControlSetPropertyInt) ? RProperty::EInt : RProperty::EByteArray;
       
    77 		_LIT_SECURITY_POLICY_PASS(KPass);
       
    78 		if (!err) err = property.Define(attr, KPass, KPass);
       
    79 		}
       
    80 	NKern::ThreadLeaveCS();
       
    81 	if (err)
       
    82 		{
       
    83 		return err;
       
    84 		}
       
    85 
       
    86 	switch (aFunction)
       
    87 		{
       
    88 		case RMemoryAccess::EControlGetPropertyInt:
       
    89 			{
       
    90 			TInt val;
       
    91 			err = property.Get(val);
       
    92 			if (!err)
       
    93 				{
       
    94 				TPckg<TInt> valBuf(val);
       
    95 				err = Kern::ThreadDesWrite(aClient, aVal, valBuf, 0);
       
    96 				}
       
    97 			break;
       
    98 			}
       
    99 		case RMemoryAccess::EControlGetPropertyDesc:
       
   100 			{
       
   101 			err = Kern::ThreadGetDesMaxLength(aClient, aVal);
       
   102 			TInt size = err;
       
   103 			if (size < 0) break;
       
   104 			
       
   105 			NKern::ThreadEnterCS();
       
   106 			HBuf8* buf = HBuf8::New(size);
       
   107 			if (!buf)
       
   108 				{
       
   109 				err = KErrNoMemory;
       
   110 				NKern::ThreadLeaveCS();
       
   111 				break;
       
   112 				}
       
   113 			err = property.Get(*buf);
       
   114 			if (!err || err == KErrOverflow)
       
   115 				{
       
   116 				TInt writeerr = Kern::ThreadDesWrite(aClient, aVal, *buf, 0, NULL);
       
   117 				if (writeerr) err = writeerr;
       
   118 				}
       
   119 			delete buf;
       
   120 			NKern::ThreadLeaveCS();
       
   121 			if (err == KErrOverflow)
       
   122 				{
       
   123 				NKern::LockSystem();
       
   124 				TPropertyStatus status;
       
   125 				property.GetStatus(status);
       
   126 				NKern::UnlockSystem();
       
   127 
       
   128 				clientParams.iActualSize = status.iSize;
       
   129 				err = Kern::ThreadRawWrite(aClient, aParams, (TAny*)&clientParams, sizeof(TProp));
       
   130 				}
       
   131 			break;
       
   132 			}
       
   133 		case RMemoryAccess::EControlSetPropertyInt:
       
   134 			{
       
   135 			err = property.Set((TInt)aVal);
       
   136 			break;
       
   137 			}
       
   138 		case RMemoryAccess::EControlSetPropertyDesc:
       
   139 			{
       
   140 			err = Kern::ThreadGetDesLength(aClient, aVal);
       
   141 			TInt size = err;
       
   142 			if (size < 0) break;
       
   143 			
       
   144 			NKern::ThreadEnterCS();
       
   145 			HBuf8* buf = HBuf8::New(size);
       
   146 			if (!buf)
       
   147 				{
       
   148 				err = KErrNoMemory;
       
   149 				NKern::ThreadLeaveCS();
       
   150 				break;
       
   151 				}
       
   152 			buf->SetLength(size);
       
   153 			err = Kern::ThreadDesRead(aClient, aVal, *buf, 0);
       
   154 			if (!err)
       
   155 				{
       
   156 				err = property.Set(*buf);
       
   157 				}
       
   158 			delete buf;
       
   159 			NKern::ThreadLeaveCS();
       
   160 			break;
       
   161 			}
       
   162 		case RMemoryAccess::EControlDeleteProperty:
       
   163 			NKern::ThreadEnterCS();
       
   164 			err = property.Delete();
       
   165 			NKern::ThreadLeaveCS();
       
   166 			break;
       
   167 		case RMemoryAccess::EControlSubscribeToProperty:
       
   168 			{
       
   169 			TBool useBtrace = (TBool)aVal;
       
   170 			TNotifyRequest* req = new TNotifyRequest(&PropertyChanged, clientParams.iCategory, clientParams.iKey, this, useBtrace);
       
   171 			err = req->iProperty.Attach(clientParams.iCategory, clientParams.iKey); // Allow non-existant properties
       
   172 			if (!err)
       
   173 				{
       
   174 				err = req->iProperty.Subscribe(req->iRequest);
       
   175 				if (err)
       
   176 					{
       
   177 					// Don't think this will ever happen
       
   178 					req->iProperty.Close();
       
   179 					req->iRequest.iPtr = NULL;
       
   180 					}
       
   181 				}
       
   182 			if (err)
       
   183 				{
       
   184 				delete req;
       
   185 				}
       
   186 			else
       
   187 				{
       
   188 				iRequests.Add(&req->iLink);
       
   189 				}
       
   190 			}
       
   191 			break;			
       
   192 		default:
       
   193 			break;
       
   194 		}
       
   195 
       
   196 	NKern::ThreadEnterCS();
       
   197 	property.Close();
       
   198 	NKern::ThreadLeaveCS();
       
   199 	return err;
       
   200 	}
       
   201 
       
   202 DPropertyAccess::~DPropertyAccess()
       
   203 	{
       
   204 	CancelNotifys();
       
   205 	}
       
   206 
       
   207 void DPropertyAccess::CancelNotifys()
       
   208 	{
       
   209 	for (SDblQueLink* link = iRequests.First(); link != NULL && link != &iRequests.iA;)
       
   210 		{
       
   211 		TNotifyRequest* request = _LOFF(link, TNotifyRequest, iLink);
       
   212 		link=link->iNext; // Do this before anything else because we'll be deleting the TNotifyRequest
       
   213 		request->iProperty.Cancel(request->iRequest);
       
   214 		request->iProperty.Close();
       
   215 		delete request;
       
   216 		}
       
   217 
       
   218 	if (iNotifyClientStatus)
       
   219 		{
       
   220 		Kern::RequestComplete(iClient, iNotifyClientStatus, KErrCancel);
       
   221 		}
       
   222 	iClientNotifyPtr = NULL;
       
   223 	}
       
   224 
       
   225 void DPropertyAccess::PropertyChanged(TAny* aPtr, TInt aReason)
       
   226 	{
       
   227 	TNotifyRequest* req = static_cast<TNotifyRequest*>(aPtr);
       
   228 	req->iPropertyAccess->DoPropertyChanged(*req, aReason);
       
   229 	}
       
   230 
       
   231 void DPropertyAccess::DoPropertyChanged(TNotifyRequest& aRequest, TInt aReason)
       
   232 	{
       
   233 	// First, rerequest
       
   234 	if (aReason == KErrNone)
       
   235 		{
       
   236 		aRequest.iProperty.Subscribe(aRequest.iRequest);
       
   237 		}
       
   238 	// Then try and notify
       
   239 	if (iNotifyClientStatus && !aRequest.iBtrace)
       
   240 		{
       
   241 		TPropNotifyResult result;
       
   242 		result.iCategory = aRequest.iCat.iUid;
       
   243 		result.iKey = aRequest.iKey;
       
   244 		result.iMissedChanges = iMissedChanges;
       
   245 		result.iError = aReason;
       
   246 		iMissedChanges = 0; // No need to lock/safeswap because we run in the context of the pubsub DFC
       
   247 		TInt err = Kern::ThreadRawWrite(iClient, iClientNotifyPtr, &result, sizeof(TPropNotifyResult));
       
   248 		Kern::RequestComplete(iClient, iNotifyClientStatus, err);
       
   249 		}
       
   250 	else if (aRequest.iBtrace)
       
   251 		{
       
   252 #ifdef FSHELL_TRACE_SUPPORT
       
   253 		TUint cat = aRequest.iCat.iUid;
       
   254 		TUint key = aRequest.iKey;
       
   255 
       
   256 		TInt intVal;
       
   257 		TInt err = aRequest.iProperty.Get(intVal);
       
   258 		if (err == KErrNone)
       
   259 			{
       
   260 			BTrace12(ExtraBTrace::EPubSub, ExtraBTrace::EPubSubIntPropertyChanged, cat, key, intVal);
       
   261 			}
       
   262 		else if (err == KErrArgument)
       
   263 			{
       
   264 			TBuf8<KMaxBTraceDataArray> buf; // No point using larger buffer, as this is the max we can output over btrace (80 bytes)
       
   265 			err = aRequest.iProperty.Get(buf);
       
   266 			if (err == KErrNone || err == KErrOverflow)
       
   267 				{
       
   268 				BTraceN(ExtraBTrace::EPubSub, ExtraBTrace::EPubSubDataPropertyChanged, cat, key, buf.Ptr(), buf.Length());
       
   269 				}
       
   270 			}
       
   271 #endif
       
   272 		}
       
   273 	else
       
   274 		{
       
   275 		iMissedChanges++;
       
   276 		}
       
   277 	}