diff -r 000000000000 -r e4d67989cc36 genericopenlibs/openenvcore/ewsd/src/ewsd.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/genericopenlibs/openenvcore/ewsd/src/ewsd.cpp Tue Feb 02 02:01:42 2010 +0200 @@ -0,0 +1,281 @@ +// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// Name : ewsd.cpp +// Part of : ewsd library +// Contains the definitions of the APIs of the emulator WSD library +// + + + +#ifdef __WINSCW__ + +#include +#include + +// Constant declarations +const TInt KMaxNumberOfProcesses = 100; +const TInt KMaxNumberOfLibraries = 50; + +// Panic strings +_LIT(KMutexGetFailure, "WSD mutex get failed"); +_LIT(KMutexReleaseFailure, "WSD mutex release failed"); + +// Mutex name +unsigned short KMutexName[] = + { + 'E', 'W', 'S', 'D', 'M', 'u', 't', 'e', 'x' + }; + +// LOCAL STRUCTURE DECLARATIONS + +// Data structure to store the WSD info associated with a particular DLL +struct TDllData + { + TUid iLibraryUid; + TAny* iPtr; + }; + +// Data structure to store the DLL information associated with a process +struct TWsdNode + { + TProcessId iPid; + TInt iFirstUnusedSlot; + struct TDllData iDllData[KMaxNumberOfLibraries]; + }; + +// WSD array variables +struct TWsdNode WsdArray[KMaxNumberOfProcesses]; +TInt LastUsedProcessSlot = -1; + +// LOCAL FUNCTION DECLARATIONS + +LOCAL_C TInt CleanupDeadProcessSlots(); +LOCAL_C void StorePls(const TInt& aProcessSlot, const TInt& aLibrarySlot, TAny* aPls, const TUid& aLibraryUid); + +// EXPORTED FUNCTION DEFINITIONS + +EXPORT_C TAny* CheckPls(const TUid& aLibraryUid) + { + TProcessId procId = RProcess().Id(); + + for (TInt i = 0; i <= LastUsedProcessSlot; ++i) + { + if (WsdArray[i].iPid == procId) + { + // This process has a slot in the WsdArray - now check + // whether its DLL array contains the specified library + TInt firstUnused = WsdArray[i].iFirstUnusedSlot; + for (TInt j = 0; j < firstUnused; ++j) + { + if (aLibraryUid == WsdArray[i].iDllData[j].iLibraryUid) + { + // The specified library is present so return the PLS object + return WsdArray[i].iDllData[j].iPtr; + } + } + break; + } + } + + // The PLS object hasn't yet been stored + return NULL; + } + +EXPORT_C TInt SetPls(TAny* aPls, const TUid& aLibraryUid) + { + TProcessId procId = RProcess().Id(); + TInt slot = -1; + + if (LastUsedProcessSlot >= 0) + { + for (TInt i = 0; i <= LastUsedProcessSlot; ++i) + { + if (!WsdArray[i].iPid.Id()) + { + if (slot == -1) + { + slot = i; + } + + continue; + } + else if (WsdArray[i].iPid == procId) + { + // We are about to set the Pls of a new library for this process + TInt firstUnused = WsdArray[i].iFirstUnusedSlot; + if (KMaxNumberOfLibraries == firstUnused) + { + // The library array is full for this process + return KErrNoMemory; + } + else + { + // Store the PLS for the specified library + StorePls(i, firstUnused, aPls, aLibraryUid); + return KErrNone; + } + } + } + + // The remainder of WsdArray is not used, so the process is + // not in it. If an empty slot hasn't yet been found then... + if (slot == -1) + { + // ... use the next unused slot in the array, if there is one + if (LastUsedProcessSlot < (KMaxNumberOfProcesses - 1)) + { + slot = LastUsedProcessSlot + 1; + } + else + { + // ... the array is full (there are no empty slots). + // Perform a clean up of the array to free any process slots that + // belong to dead processes to see if there is a slot that we can reuse + TInt slotToReuse = CleanupDeadProcessSlots(); + if (slotToReuse == -1) + { + // There are no reusable slots in the process array + return KErrNoMemory; + } + slot = slotToReuse; + } + } + } + else + { + slot = 0; + } + + // Store the PLS for the specified library + StorePls(slot, 0, aPls, aLibraryUid); + + // Store the process details too as this process is new to WsdArray + WsdArray[slot].iPid = procId; + + // Update the LastUsedProcessSlot if necessary + if (slot > LastUsedProcessSlot) + { + LastUsedProcessSlot = slot; + } + + return KErrNone; + } + +EXPORT_C TAny* AllocatePls(const TInt& aSize) + { + return VirtualAlloc(NULL, + aSize, + MEM_COMMIT | MEM_RESERVE, + PAGE_READWRITE); + } + +EXPORT_C TInt FreePls(TAny* aPls) + { + if (!VirtualFree(aPls, 0, MEM_RELEASE)) + { + return KErrAccessDenied; + } + aPls = NULL; + return KErrNone; + } + +EXPORT_C TAny* ObtainPlsMutex() + { + // Get a handle to the mutex (the mutex will be created + // if it doesn't already exist) and then wait to acquire + // ownership of the mutex + HANDLE mutexHandle = CreateMutex(NULL, FALSE, KMutexName); + if ((!mutexHandle) || (WaitForSingleObject(mutexHandle, INFINITE) == WAIT_FAILED)) + { + User::Panic(KMutexGetFailure, KErrAccessDenied); + } + + return mutexHandle; + } + +EXPORT_C void ReleasePlsMutex(TAny* aMutexHandle) + { + if (!ReleaseMutex(aMutexHandle)) + { + User::Panic(KMutexReleaseFailure, KErrAccessDenied); + } + } + +// LOCAL FUNCTIONS DEFINITIONS + +/** +Iterates through the WSD array and frees each slot that belongs to a dead process +(the stored data is reset and all associated PLS memory is freed). +Returns the index of the first freed slot if at least one slot was freed, +otherwise -1 +*/ +LOCAL_C TInt CleanupDeadProcessSlots() + { + TInt firstReusableSlot = -1; + TUid nullUid = TUid::Null(); + LastUsedProcessSlot = -1; + RProcess proc; + for (TInt i = 0; i < KMaxNumberOfProcesses; ++i) + { + if(proc.Open(WsdArray[i].iPid) == KErrNone) + { + if(proc.ExitType()==EExitPending) + { + LastUsedProcessSlot = i; + proc.Close(); + continue; + } + else + proc.Close(); + + } + + // Process with the given name does not exist in + // the system, so the slot could be reused + WsdArray[i].iPid = 0; + + + // Free all of the PLS memory associated with this process + TInt firstUnused = WsdArray[i].iFirstUnusedSlot; + WsdArray[i].iFirstUnusedSlot = 0; + for (TInt j = 0; j < firstUnused; ++j) + { + FreePls(WsdArray[i].iDllData[j].iPtr); + WsdArray[i].iDllData[j].iLibraryUid = nullUid; + } + + if (firstReusableSlot == -1) + { + // Set the slot to reuse + firstReusableSlot = i; + } + } + + return firstReusableSlot; +} + +/** +Stores the specified PLS object and library TUid at the specified location in the WSD array. +Takes as parameters the process slot to use in the WSD array, the slot to use in the library +array associated with the given process, the PLS object to be stored and the TUid of the +library DLL that the PLS object belongs to +*/ +LOCAL_C void StorePls(const TInt& aProcessSlot, const TInt& aLibrarySlot, TAny* aPls, const TUid& aLibraryUid) + { + WsdArray[aProcessSlot].iDllData[aLibrarySlot].iPtr = aPls; + WsdArray[aProcessSlot].iDllData[aLibrarySlot].iLibraryUid = aLibraryUid; + ++WsdArray[aProcessSlot].iFirstUnusedSlot; + } + +#endif // __WINSCW__