os/boardsupport/emulator/emulatorbsp/specific/property.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
child 1 260cb5ec6c19
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 1998-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 "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 // wins\specific\property.cpp
    15 // Emulator property management for emulator settings
    16 // 
    17 //
    18 
    19 #define _CRTIMP			// we want to use the static runtime library
    20 
    21 #define __INCLUDE_CAPABILITY_NAMES__
    22 #include "variant.h"
    23 #include <string.h>
    24 #include <stdlib.h>
    25 #include <emulator.h>
    26 
    27 #ifdef _DEBUG
    28 #define _DUMP_PROPERTY
    29 #endif
    30 
    31 const char* KDefaultMachineName = "epoc";
    32 const char* KDefaultTestMachineName = "defaulttest";
    33 
    34 // name of the environment variable to check for default path
    35 const char* KDefaultEpocRootName = "EPOCROOT";
    36 
    37 TInt ScreenId=0;
    38 
    39 // At the point this is created there is no kernel heap available
    40 // So all memory allocation is done from a custom allocator
    41 
    42 const TInt KMaxTokenLength = 255;
    43 
    44 class Allocator
    45 	{
    46 	enum {ETotalMemory=0x10000};	// 64K
    47 public:
    48 	Allocator();
    49 	TAny* Alloc(TInt aSize);
    50 	TAny* Realloc(TAny* aCell, TInt aSize);
    51 	void Free(TAny* aCell);
    52 private:
    53 	TUint iBuf[ETotalMemory];
    54 	TUint* iFree;
    55 	};
    56 
    57 Allocator::Allocator()
    58 	:iFree(iBuf)
    59 	{}
    60 
    61 TAny* Allocator::Alloc(TInt aSize)
    62 	{
    63 	aSize = (aSize + 7) >> 2;
    64 	if (iFree + aSize > iBuf + ETotalMemory)
    65 		return NULL;
    66 	TUint* p = iFree;
    67 	iFree += aSize;
    68 	*p++ = aSize;
    69 	return p;
    70 	}
    71 
    72 TAny* Allocator::Realloc(TAny* aCell, TInt aSize)
    73 	{
    74 	if (!aCell)
    75 		return Alloc(aSize);
    76 
    77 	TUint* p = (TUint*)aCell;
    78 	TInt size = *--p;
    79 	if (iFree == p + size)
    80 		{
    81 		aSize = (aSize + 7) >> 2;
    82 		if (p + aSize > iBuf + ETotalMemory)
    83 			return NULL;
    84 		iFree = p + aSize;
    85 		*p = aSize;
    86 		return aCell;
    87 		}
    88 
    89 	TAny* newp = Alloc(aSize);
    90 	if (newp)
    91 		{
    92 		memcpy(newp, aCell, size*sizeof(TUint));
    93 		Free(aCell);
    94 		}
    95 	return newp;
    96 	}
    97 
    98 void Allocator::Free(TAny* )
    99 	{
   100 	}
   101 
   102 Allocator TheAllocator;
   103 
   104 ///////
   105 
   106 char* Duplicate(const char* aString)
   107 	{
   108 	if (aString == NULL)
   109 		aString = "";
   110 
   111 	TInt size = strlen(aString) + 1;
   112 	char* p = (char*)TheAllocator.Alloc(size);
   113 	if (p)
   114 		memcpy(p, aString, size);
   115 	return p;
   116 	}
   117 
   118 // Properties class implementation
   119 
   120 Properties::Properties()
   121 	:iEntries(NULL),iCount(0),iSize(0)
   122 	{}
   123 
   124 const char* Properties::Insert(TInt aIndex, const char* aProperty, const char* aValue)
   125 	{
   126 	if (iCount == iSize)
   127 		{
   128 		TInt size = iSize == 0 ? 8 : iSize*2;
   129 		TAny* array = TheAllocator.Realloc(iEntries, size*sizeof(SEntry));
   130 		if (array == NULL)
   131 			return NULL;
   132 		iEntries = (SEntry*)array;
   133 		iSize = size;
   134 		}
   135 
   136 	char* prop = Duplicate(aProperty);
   137 	if (prop == NULL)
   138 		return NULL;
   139 	char* value = Duplicate(aValue);
   140 	if (value == NULL)
   141 		TheAllocator.Free(prop);
   142 	else
   143 		{
   144 		SEntry* e = &iEntries[aIndex];
   145 		memmove(e+1, e, (iCount-aIndex)*sizeof(SEntry));
   146 		e->iProperty = prop;
   147 		e->iValue = value;
   148 		++iCount;
   149 		}
   150 	return value;
   151 	}
   152 
   153 const char* Properties::Replace(const char* aProperty, const char* aValue)
   154 	{
   155 	TInt ix = Find(aProperty);
   156 	if (ix < 0)
   157 		return Insert(~ix, aProperty, aValue);
   158 	// replacing a property
   159 	SEntry& e = iEntries[ix];
   160 	char* value = Duplicate(aValue);
   161 	if (value != NULL)
   162 		{
   163 		TheAllocator.Free(e.iValue);
   164 		e.iValue = value;
   165 		}
   166 	return value;
   167 	}
   168 
   169 const char* Properties::Append(const char* aProperty, const char* aValue)
   170 	{
   171 	TInt ix = Find(aProperty);
   172 	if (ix < 0)
   173 		return Insert(~ix, aProperty, aValue);
   174 
   175 	// append a property
   176 	SEntry& e = iEntries[ix];
   177 	TInt size = strlen(e.iValue) + strlen(aValue) + 2;
   178 	char* value = (char*)TheAllocator.Realloc(e.iValue, size);
   179 	if (value != NULL)
   180 		{
   181 		strcat(value, ";");
   182 		strcat(value, aValue);
   183 		e.iValue = value;
   184 		}
   185 	return value;
   186 	}
   187 
   188 TInt Properties::GetString(const char* aProperty, const char*& aValue) const
   189 	{
   190 	TInt ix = Find(aProperty);
   191 	if (ix < 0)
   192 		return KErrNotFound;
   193 	aValue = iEntries[ix].iValue;
   194 	return KErrNone;
   195 	}
   196 
   197 TInt Properties::GetInt(const char* aProperty, TInt& aValue) const
   198 	{
   199 	TInt ix = Find(aProperty);
   200 	if (ix < 0)
   201 		return KErrNotFound;
   202 	char* value = iEntries[ix].iValue;
   203 	char* end;
   204 	TBool neg = *value=='-';
   205 	value += neg;
   206 	long val = strtoul(value, &end, 0);
   207 	if(neg)
   208 		{
   209 		if(val<0)
   210 			return KErrArgument;
   211 		val = -val;
   212 		}
   213 	if (*end != '\0')
   214 		return KErrArgument;
   215 	aValue = val;
   216 	return KErrNone;
   217 	}
   218 
   219 TInt Properties::GetBool(const char* aProperty, TBool& aValue, TBool aDefaultValue) const
   220 	{
   221 	TInt ix = Find(aProperty);
   222 	if (ix < 0)
   223 		{
   224 		aValue = aDefaultValue;
   225 		return KErrNone;
   226 		}
   227 	const char* value=iEntries[ix].iValue;
   228 	if (_stricmp(value, "on")==0 || _stricmp(value, "yes")==0 || _stricmp(value, "1")==0 || strlen(value)==0)
   229 		{
   230 		aValue = ETrue;
   231 		return KErrNone;
   232 		}
   233 	if (_stricmp(value, "off")==0 || _stricmp(value, "no")==0 || _stricmp(value, "0")==0 )
   234 		{
   235 		aValue = EFalse;
   236 		return KErrNone;
   237 		}
   238 
   239 	// Bool property has an illegal value!
   240 	return KErrArgument;
   241 	}
   242 
   243 TInt Properties::Find(const char* aProperty) const
   244 //
   245 // Lookup a property in the table
   246 // return index (>=0) if found, ~insertion-point (<0) if not
   247 //
   248 	{
   249 	TInt l = 0, r = iCount;
   250 	while (l < r)
   251 		{
   252 		TInt m = (l + r) >> 1;
   253 		const SEntry& e = iEntries[m];
   254 		TInt k = _stricmp(aProperty,e.iProperty);
   255 		if (k < 0)
   256 			r = m;
   257 		else if (k > 0)
   258 			l = m + 1;
   259 		else
   260 			return m;
   261 		}
   262 	return ~l;
   263 	}
   264 
   265 #ifdef _DUMP_PROPERTY
   266 void Properties::Dump() const
   267 	{
   268 	for (TInt i = 0; i < iCount; ++i)
   269 		{
   270 		const SEntry& e = iEntries[i];
   271 		char buf[512];
   272 		strcpy(buf, e.iProperty);
   273 		TInt len = strlen(e.iValue);
   274 		if (len)
   275 			{
   276 			strcat(buf, " = ");
   277 			if (len <= 256)
   278 				strcat(buf, e.iValue);
   279 			else
   280 				{
   281 				strncat(buf, e.iValue, 256);
   282 				strcat(buf, "...");
   283 				}
   284 			}
   285 		strcat(buf, "\r\n");
   286 		OutputDebugStringA(buf);
   287 		}
   288 	}
   289 #endif
   290 
   291 // Property related variant functions
   292 
   293 TInt Wins::EmulatorHal(TInt aFunction, TAny* a1, TAny* a2)
   294 	{
   295 	TInt r=KErrNone;
   296 	switch(aFunction)
   297 		{
   298 		case EEmulatorHalStringProperty:
   299 			return iProperties.GetString((const char*)a1,*(const char**)a2);
   300 		case EEmulatorHalIntProperty:
   301 			return iProperties.GetInt((const char*)a1,*(TInt*)a2);
   302 		case EEmulatorHalBoolProperty:
   303 			return iProperties.GetBool((const char*)a1,*(TBool*)a2);
   304 		case EEmulatorHalMapFilename:
   305 			return MapFilename(*(const TDesC*)a1,*(TDes*)a2);
   306 		case EEmulatorHalSetFlip:
   307 			{
   308 			if (iUi)
   309 				{
   310 				TInt screen = (TInt)a2;
   311 				if((TUint)screen < (TUint)iUi->NumberOfScreens())
   312 					return iUi->SetFlip(TEmulatorFlip(TInt(a1)),screen);
   313 				}
   314 			break;
   315 			}
   316 		case EEmulatorHalColorDepth:
   317 			{
   318 			TUint colorDepth = KDefaultColorDepth;
   319 			if(iUi)
   320 				{
   321 				if((TUint)a2 < (TUint)iUi->NumberOfScreens())
   322 					colorDepth = iUi->ColorDepth((TInt)a2);
   323 				}
   324 			*(TUint*)a1 = colorDepth;
   325 			return KErrNone;
   326 			}
   327 		case EEmulatorHalCPUSpeed:
   328 			if (a1)
   329 				return SetCpuSpeed(TUint(a2)/1000);
   330 			*(TInt*)a2 = iCpuSpeed ? iCpuSpeed * 1000 : 1;
   331 			return KErrNone;
   332 		case EEmulatorHalNumberOfScreens:
   333 			*(TInt*)a2 = iUi ? iUi->NumberOfScreens() : 1;
   334 			return KErrNone;
   335 		case EEmulatorHalSetDisplayChannel:
   336 			if (iUi && (TUint)a1 < (TUint)iUi->NumberOfScreens())
   337 				{
   338 				r = iUi->SetDisplayChannel((TInt)a1, static_cast<DDisplayChannel*>(a2));
   339 				}
   340 			else
   341 				{
   342 				r = KErrNotSupported;
   343 				}
   344 			break;
   345 		default:
   346 			r=KErrNotSupported;
   347 			break;
   348 		}
   349 	return r;
   350 	}
   351 
   352 const char* KExtensionListNormal = "btracex.ldd;hcr.dll;winsgui;elocd.ldd;medint.pdd;medlfs.pdd;medmmc.pdd;epbusmmc.dll;epbusv.dll";
   353 const char* KExtensionUsiiNand = "?medusiiw.pdd";
   354 const char* KExtensionUsiiNandLoader = "?medusiiws.pdd";
   355 const char* KExtensionUsiiNandTest = "?medusiiwt.pdd";
   356 
   357 
   358 
   359 
   360 const int KMaxEpocRootSize = 120;
   361 
   362 TInt Wins::InitProperties(TBool aRunExe)
   363 	{
   364 	if (iProperties.Replace("MachineName", KDefaultMachineName) == NULL)
   365 		return KErrNoMemory;
   366 
   367     char epocRoot[KMaxEpocRootSize];
   368 
   369     TInt total = GetEnvironmentVariableA( KDefaultEpocRootName, epocRoot, KMaxEpocRootSize);
   370 
   371     if (total != 0)
   372 		{
   373 	    if (iProperties.Replace("EpocRoot", epocRoot) == NULL)
   374     	    return KErrNoMemory;
   375 		}
   376 
   377 	if (iProperties.Append("Extension", KExtensionListNormal) == NULL)
   378 		return KErrNoMemory;
   379 
   380 	char overrideCDrive[MAX_PATH];
   381 	overrideCDrive[0] = '\0';
   382 	TInt r = ProcessCommandLine(aRunExe, overrideCDrive);
   383 	if (r != KErrNone)
   384 		return r;
   385 
   386 	r = SetupPaths();
   387 	if (r != KErrNone)
   388 		return r;
   389 
   390 	r = LoadProperties();
   391 	if (r != KErrNone)
   392 		return r;
   393 
   394 	//	get Unistore II Media Driver type from epoc.ini
   395 	const char* value = NULL;
   396 	
   397 
   398 	iProperties.GetString("NandDriverType", value);
   399 	if (value)
   400 		{
   401 		if (value && _stricmp("XSR",value)==0)
   402 			{
   403 			// epoc.ini "NandDriverType=XSR" for XSR/Unistore-II driver
   404 			if (iProperties.Append("Extension", KExtensionUsiiNand) == NULL)
   405 				return KErrNoMemory;		
   406 			}
   407 		else if (value && _stricmp("XSRNandloader",value)==0)
   408 			{
   409 			// epoc.ini "NandDriverType=XSRNandloader" for XSR/Unistore-II nandloader driver
   410 			if (iProperties.Append("Extension", KExtensionUsiiNandLoader) == NULL)
   411 				return KErrNoMemory;		
   412 			}
   413 		else if (value && _stricmp("XSRTest",value)==0)
   414 			{
   415 			// epoc.ini "NandDriverType=XSRTest" for XSR/Unistore-II test driver
   416 			if (iProperties.Append("Extension", KExtensionUsiiNandTest) == NULL)
   417 				return KErrNoMemory;
   418 			}
   419 		else	
   420 			{
   421 			// If epoc.ini contains "NandDriverType=???" but ??? not equal to any
   422 			// of above XSR driver types then load production/release XSR
   423 			// driver
   424 			if (iProperties.Append("Extension", KExtensionUsiiNand) == NULL)
   425 				return KErrNoMemory;
   426 
   427 			}
   428 		}
   429 	else
   430 		{
   431 		// Load the production/release XSR driver, if value is NULL
   432 		if (iProperties.Append("Extension", KExtensionUsiiNand) == NULL)
   433 			return KErrNoMemory;
   434 
   435 		}
   436 	
   437 
   438 //	load additional configuration specific properties
   439 
   440 //	get the multi property "configuration"
   441 	value = NULL;
   442 	iProperties.GetString("configuration", value);
   443 	
   444 //	load each one of these
   445 //	check for any screen specific properties in the main epoc.ini
   446 //	if configuration property is set
   447 	if (value && !iConfigPropertySet)	//configuration
   448 		{
   449 		iConfigId = 0;
   450 		char configFileName[100];
   451 		do
   452 			{
   453 			//load each set of properties
   454 
   455 		   const char * pdest = strchr(value, ';');
   456 		   TInt result = pdest - value;
   457 		   if(pdest)
   458 			   {
   459 			   strncpy(configFileName, value, result);
   460 			   configFileName[result] = '\0';
   461 			   value = value + result + 1;
   462 			   }
   463 		   else
   464 			   {
   465 			   strcpy(configFileName, value);
   466 			   value += strlen(value);
   467 			   }
   468 
   469 			r = LoadConfigSpecificProperties(configFileName);
   470 			if (r == KErrNone)
   471 				iConfigId++;
   472 			}
   473 		while(*value);
   474 		}
   475 
   476 	char scr[30];
   477 	//if iConfigId is zero, there is only 1 configuration
   478 	wsprintfA(scr, "ConfigCount %d", iConfigId ? iConfigId : 1);
   479 	r = AddProperty(scr, scr+strlen(scr));
   480 	if (r != KErrNone)
   481 		return r;
   482 
   483 	r = SetupMediaPath();
   484 	if (r != KErrNone)
   485 		return r;
   486 
   487 	if (overrideCDrive[0] != '\0')
   488 		SetupDrive('c', overrideCDrive);
   489 
   490 	if (iProperties.Append("Extension", "exstart") == NULL)
   491 		return KErrNoMemory;
   492 
   493 #ifdef _DUMP_PROPERTY
   494 	iProperties.Dump();
   495 #endif
   496 
   497 	return KErrNone;
   498 	}
   499 
   500 char* skipws(char* aPtr)
   501 	{
   502 	while (isspace(*aPtr))
   503 		++aPtr;
   504 	return aPtr;
   505 	}
   506 
   507 char* skiptok(char* aPtr)
   508 	{
   509 	if (*aPtr == '\"')
   510 		{
   511 		++aPtr;
   512 		while (*aPtr && *aPtr++ != '\"')
   513 			{}
   514 		}
   515 	else
   516 		{
   517 		while (*aPtr && !isspace(*aPtr))
   518 			++aPtr;
   519 		}
   520 	return aPtr;
   521 	}
   522 
   523 #ifdef _DEBUG
   524 struct TDebugTrace
   525 	{
   526 	const char* iName;
   527 	TInt iMask;
   528 	};
   529 
   530 // Only the first 32 trace bits can be defined using these values
   531 // "ALWAYS" in this context means all of the first 32 bits not all 256 bits
   532 const TDebugTrace KTraceValues[] =
   533 	{
   534 	{"ALWAYS", KALWAYS},
   535 	{"BOOT", 1<<KBOOT},
   536 	{"DEVICE", 1<<KDEVICE},
   537 	{"DFC", 1<<KDFC},
   538 	{"DLL", 1<<KDLL},
   539 	{"EVENT", 1<<KEVENT},      
   540 	{"EXEC", 1<<KEXEC},
   541 	{"DEBUGGER", 1<<KDEBUGGER},
   542 	{"EXTENSION", 1<<KEXTENSION},
   543 	{"FAIL", 1<<KFAIL},
   544 	{"HARDWARE", 1<<KHARDWARE},
   545 	{"IPC", 1<<KIPC},
   546 	{"LOCDRV", 1<<KLOCDRV},
   547 	{"MEMTRACE", 1<<KMEMTRACE},
   548 	{"MMU", 1<<KMMU},
   549 	{"NKERN", 1<<KNKERN},
   550 	{"OBJECT", 1<<KOBJECT},
   551 	{"PANIC", 1<<KPANIC},
   552 	{"PBUS1", 1<<KPBUS1},
   553 	{"PBUS2", 1<<KPBUS2},
   554 	{"PBUSDRV", 1<<KPBUSDRV},
   555 	{"POWER", 1<<KPOWER},      
   556 	{"PROC", 1<<KPROC},
   557 	{"SCHED", 1<<KSCHED},
   558 	{"SCHED2", 1<<KSCHED2},
   559 	{"SCRATCH", 1<<KSCRATCH},
   560 	{"SEMAPHORE", 1<<KSEMAPHORE},
   561 	{"SERVER", 1<<KSERVER},
   562 	{"THREAD", 1<<KTHREAD},
   563 	{"THREAD2", 1<<KTHREAD2},
   564 	{"TIMING", 1<<KTIMING},
   565 	{"DMA", 1<<KDMA},
   566 	{"MMU2", 1<<KMMU2}
   567 	};
   568 const TInt KMaxTraceName = 9;
   569 const TInt KCountTraceValues = sizeof(KTraceValues)/sizeof(TDebugTrace);
   570 
   571 static const TDebugTrace* TraceType(const char* aTrace, TInt aLen)
   572 	{
   573 	if (aLen > KMaxTraceName)
   574 		return 0;
   575 
   576 	char name[KMaxTraceName + 1];
   577 	strncpy(name, aTrace, aLen);
   578 	name[aLen] = '\0';
   579 
   580 	for (TInt i=KCountTraceValues; --i>=0;)
   581 		{
   582 		if (_stricmp(name, KTraceValues[i].iName)==0)
   583 			return &KTraceValues[i];
   584 		}
   585 	return 0;
   586 	}
   587 #endif
   588 
   589 TInt Wins::DebugMask()
   590 	{
   591 	TInt mask = KDefaultDebugMask;
   592 	if (iProperties.GetInt("DebugMask", mask) != KErrArgument)
   593 		return mask;
   594 #ifdef _DEBUG
   595 	// allow text ones
   596 	const char* e;
   597 	if (iProperties.GetString("DebugMask", e) != KErrNone)
   598 		return mask;
   599 
   600 	for (;;)
   601 		{
   602 		char* p = skipws((char*)e);
   603 		if (*p == 0)
   604 			break;
   605 		e = skiptok(p);
   606 		TBool add = ETrue;
   607 		if (*p == '+')
   608 			++p;
   609 		else if (*p == '-')
   610 			{
   611 			add = EFalse;
   612 			++p;
   613 			}
   614 		const TDebugTrace* type = TraceType(p, e - p);
   615 		if (type)
   616 			{
   617 			if (add)
   618 				mask |= type->iMask;
   619 			else
   620 				mask &= ~type->iMask;
   621 			}
   622 		}
   623 #endif
   624 	return mask;
   625 	}
   626 
   627 TUint32 Wins::KernelConfigFlags()
   628 	{
   629 	TUint32 flags = 0;
   630 	TBool b;
   631 
   632 	b=0;
   633 	iProperties.GetBool("PlatSecEnforcement",b,EFalse);
   634 	if(b) flags |= EKernelConfigPlatSecEnforcement;
   635 	Wins::EarlyLogging("PlatSecEnforcement ",b?"ON":"OFF");
   636 
   637 	b=0;
   638 	iProperties.GetBool("PlatSecDiagnostics",b,EFalse);
   639 	if(b) flags |= EKernelConfigPlatSecDiagnostics;
   640 	Wins::EarlyLogging("PlatSecDiagnostics ",b?"ON":"OFF");
   641 
   642 	b=0;
   643 	iProperties.GetBool("PlatSecProcessIsolation",b,EFalse);
   644 	if(b) flags |= EKernelConfigPlatSecProcessIsolation;
   645 	Wins::EarlyLogging("PlatSecProcessIsolation ",b?"ON":"OFF");
   646 
   647 	b=0;
   648 	iProperties.GetBool("PlatSecEnforceSysBin",b,EFalse);
   649 	if(b) flags |= EKernelConfigPlatSecEnforceSysBin;
   650 	Wins::EarlyLogging("PlatSecEnforceSysBin ",b?"ON":"OFF");
   651 
   652 	b=0;
   653 	iProperties.GetBool("CrazyScheduling",b,EFalse);
   654 	if(b) flags |= EKernelConfigCrazyScheduling;
   655 	Wins::EarlyLogging("CrazyScheduling ",b?"ON":"OFF");
   656 
   657 	return flags;
   658 	}
   659 
   660 void Wins::DisabledCapabilities(SCapabilitySet& aCapabilities)
   661 	{
   662 	const char* text;
   663 	if(iProperties.GetString("PlatSecDisabledCaps", text)!=KErrNone)
   664 		text = "NONE";
   665 	Wins::EarlyLogging("PlatSecDisabledCaps ",text);
   666 	ParseCapabilitiesArg(aCapabilities,text);
   667 	}
   668 
   669 #define PARSE_CAPABILITIES_ERROR(aMessage) Wins::EarlyLogging(aMessage,0)
   670 #define PARSE_CAPABILITIES_ERROR2(aMessage,aArg) Wins::EarlyLogging(aMessage,aArg)
   671 #define strnicmp _strnicmp
   672 
   673 TInt Wins::ParseCapabilitiesArg(SCapabilitySet& aCapabilities, const char *aText)
   674 //
   675 // This is a cun'n'paste copy of the function in TOOLS\E32TOOLS\HOST\H_UTIL.CPP
   676 // Keep both of these versions up to date with each other
   677 //
   678 	{
   679 	memset(&aCapabilities,0,sizeof(aCapabilities));
   680 	char c;
   681 	while((c=*aText)!=0)
   682 		{
   683 		if(c<=' ')
   684 			{
   685 			++aText;
   686 			continue;
   687 			}
   688 		int invert=0;
   689 		if(c=='+')
   690 			{
   691 			++aText;
   692 			c=*aText;
   693 			}
   694 		if(c=='-')
   695 			{
   696 			invert=1;
   697 			++aText;
   698 			}
   699 		const char* name = aText;
   700 		while((c=*aText)>' ')
   701 			{
   702 			if(c=='-' || c=='+')
   703 				break;
   704 			++aText;
   705 			}
   706 		TInt n = aText-name;
   707 		TInt i;
   708 
   709 		if(n==3 && strnicmp("all",name,n)==0)
   710 			{
   711 			if(invert)
   712 				{
   713 				PARSE_CAPABILITIES_ERROR("Capability '-ALL' not allowed");
   714 				return KErrArgument;
   715 				}
   716 			for(i=0; i<ECapability_Limit; i++)
   717 				{
   718 				if(CapabilityNames[i])
   719 					aCapabilities[i>>5] |= (1<<(i&31));
   720 				}
   721 			continue;
   722 			}
   723 
   724 		if(n==4 && strnicmp("none",name,n)==0)
   725 			{
   726 			if(invert)
   727 				{
   728 				PARSE_CAPABILITIES_ERROR("Capability '-NONE' not allowed");
   729 				return KErrArgument;
   730 				}
   731 			memset(&aCapabilities,0,sizeof(aCapabilities));
   732 			continue;
   733 			}
   734 
   735 		for(i=0; i<ECapability_Limit; i++)
   736 			{
   737 			const char* cap = CapabilityNames[i];
   738 			if(!cap)
   739 				continue;
   740 			if((int)strlen(cap)!=n)
   741 				continue;
   742 			if(strnicmp(cap,name,n)!=0)
   743 				continue;
   744 			break;
   745 			}
   746 		if(i>=ECapability_Limit)
   747 			{
   748 			char badName[32];
   749 			if(n>=sizeof(badName)) n=sizeof(badName)-1;
   750 			memcpy(badName,name,n);
   751 			badName[n]=0;
   752 			PARSE_CAPABILITIES_ERROR2("Unrecognised capability name: ",badName);
   753 			return KErrArgument;
   754 			}
   755 		if(invert)
   756 			aCapabilities[i>>5] &= ~(1<<(i&31));
   757 		else
   758 			aCapabilities[i>>5] |= (1<<(i&31));
   759 		}
   760 	return KErrNone;
   761 	}
   762 
   763 TInt Wins::AddProperty(char* aProperty, const char* aEol)
   764 	{
   765 	const char* tok = aProperty;
   766 	int c;
   767 	do
   768 		{
   769 		if (aProperty == aEol)
   770 			{
   771 			// boolean property
   772 			if (_stricmp(tok, "_NewScreen_") == 0)
   773  				{
   774  				++ScreenId;
   775  				return KErrNone;
   776  				}
   777 			else
   778 				{
   779 				char newtok[KMaxTokenLength];
   780 				if (ConfigSpecificProperty(tok))
   781 					{
   782 					wsprintfA(newtok, "Configuration[%d]", iConfigId);
   783 					strcat(newtok, tok);
   784 					tok = newtok;
   785 					}
   786 				}
   787 			return iProperties.Replace(tok, NULL) == NULL ? KErrNoMemory : KErrNone;
   788 			}
   789 		c=*aProperty++;
   790 		} while (isalnum(c) || c=='_');
   791 	aProperty[-1]='\0';	// terminate property name
   792 	while (isspace(c))
   793 		c=*aProperty++;
   794 	TBool append=ETrue;
   795 	if (c=='=')
   796 		{
   797 		append=EFalse;
   798 		c=*aProperty++;
   799 		}
   800 	else if (c=='+' && *aProperty=='=')
   801 		{
   802 		++aProperty;
   803 		c=*aProperty++;
   804 		}
   805 	while (isspace(c))
   806 		c=*aProperty++;
   807 	--aProperty;	// point back to value
   808 
   809 	if (_strnicmp(tok, "_epoc_drive_", 12) == 0)
   810 		return SetupDrive(tok[12], aProperty);
   811 	else
   812 		{
   813 		char newtok[KMaxTokenLength];
   814 		if (ConfigSpecificProperty(tok))
   815 			{
   816 			if (ScreenSpecificProperty(tok))
   817 				{
   818 				wsprintfA(newtok, "Configuration[%d][%d]", iConfigId, ScreenId);
   819 				}
   820 			else
   821 				{
   822 				wsprintfA(newtok, "Configuration[%d]", iConfigId);
   823 				}
   824 			strcat(newtok, tok);
   825 			tok = newtok;
   826 			}
   827 		if (append)
   828 			return iProperties.Append(tok, aProperty) == NULL ? KErrNoMemory : KErrNone;
   829 		else
   830 			return iProperties.Replace(tok, aProperty) == NULL ? KErrNoMemory : KErrNone;
   831 		}
   832 	}
   833 
   834 TInt Wins::ProcessCommandLine(TBool aRunExe, char* aCDrive)
   835 	{
   836 	if (aRunExe)
   837 		{
   838 		char exe[MAX_PATH];
   839 		DWORD len=GetModuleFileNameA(NULL, exe, MAX_PATH);
   840 		if (len == 0)
   841 			return KErrGeneral;
   842 		exe[len] = '\0';
   843 		const char* base = strrchr(exe, '\\') + 1;
   844 		if (iProperties.Replace("AutoRun", base) == NULL)
   845 			return KErrNoMemory;
   846 		}
   847 
   848 	char* cmd = skipws(skiptok(GetCommandLineA()));
   849 	if (strstr(cmd, "--") != NULL)
   850 		{
   851 		for (;;)
   852 			{
   853 			cmd = strchr(cmd, '-') + 1;
   854 			TInt opt = *cmd++;
   855 			if (opt == '-')
   856 				break;
   857 			char* end = skiptok(cmd);
   858 			*end = '\0';
   859 			switch (tolower(opt))
   860 				{
   861 			    case 'd':
   862 				    {
   863 				    TInt r = AddProperty(cmd, end);
   864 				    if (r != KErrNone)
   865 				    	return r;
   866 				    }
   867 				    break;
   868 			    case 'm':
   869 			    	// specify base name for .INI file
   870 				    if (iProperties.Replace("MachineName", cmd) == NULL)
   871 				    	return KErrNoMemory;
   872 				    break;
   873 			    case 'l':
   874 			    	// specify language
   875 			    	if (iProperties.Replace("TheMachineLanguageIndex", cmd) == NULL)
   876 			    		return KErrNoMemory;
   877 			    	break;
   878 		    	case 'c':
   879 		    		// specify path for emulated C drive
   880 			    	{
   881 			    	DWORD len=GetFullPathNameA(cmd, MAX_PATH, aCDrive, NULL);
   882 			    	if (len==0 || len >= MAX_PATH)
   883 			    		aCDrive[0] = '\0';
   884 			    	}
   885 			        break;
   886 			    case 't':
   887 			    	// specify the temp path as the emulated C drive
   888 			    	{
   889 			    	DWORD len=GetTempPathA(MAX_PATH, aCDrive);
   890 			    	if (len==0 || len >= MAX_PATH)
   891 			    		aCDrive[0] = '\0';
   892 			    	}
   893 			    	break;
   894 				}
   895 			cmd = end+1;
   896 			}
   897 		cmd = skipws(cmd);
   898 		}
   899 
   900 	if (aRunExe && iProperties.Replace("CommandLine", cmd) == NULL)
   901 		return KErrNoMemory;
   902 
   903 	return KErrNone;
   904 	}
   905 
   906 TInt Wins::LoadConfigSpecificProperties(const char * aFile)
   907 	{
   908 	const char* path;
   909 	TInt r = iProperties.GetString("EmulatorDataPath", path);
   910 	if (r != KErrNone)
   911 		return r;
   912 
   913 	char file[KMaxFileName + 1];
   914 	strcpy(file, path);
   915 	strcat(file, aFile);
   916 
   917 	char* iniData;
   918 	r = ReadIniFile(file, iniData);
   919 	if (r == KErrNone)
   920 		{
   921 		r = ReadProperties(iniData);
   922 		VirtualFree(iniData, 0, MEM_RELEASE);
   923 		}
   924 	else if (r == KErrNotFound)
   925 		r = KErrNotFound;
   926 
   927 	return r;
   928 
   929 	}
   930 
   931 
   932 
   933 TInt Wins::LoadProperties()
   934 	{
   935 	const char* path;
   936 	TInt r = iProperties.GetString("EmulatorDataPath", path);
   937 	if (r != KErrNone)
   938 		return r;
   939 	const char* name;
   940 	r = iProperties.GetString("MachineName", name);
   941 	if (r != KErrNone)
   942 		return r;
   943 retry:
   944 	char file[KMaxFileName + 1];
   945 	strcpy(file, path);
   946 	strcat(file, name);
   947 	strcat(file, ".ini");
   948 
   949 	char* iniData;
   950 	r = ReadIniFile(file, iniData);
   951 	if (r == KErrNone)
   952 		{
   953 		r = ReadProperties(iniData);
   954 		VirtualFree(iniData, 0, MEM_RELEASE);
   955 		}
   956 	else if (r == KErrNotFound)
   957 		{
   958 		if(_stricmp(name,KDefaultMachineName)==0)
   959 			{
   960 			// try test ini file
   961 			name = KDefaultTestMachineName;
   962 			goto retry;
   963 			}
   964 		r = KErrNone;		// no ini file - oh well
   965 		}
   966 
   967 	return r;
   968 	}
   969 
   970 TInt Wins::ReadProperties(char* aData)
   971 	{
   972 	ScreenId = 0;
   973 	while (*aData)
   974 		{
   975 		char* beg = aData;
   976 		char* eol = strchr(beg, '\n');
   977 		aData = eol+1;
   978 		if (eol == beg)
   979 			continue;
   980 		if (eol[-1] == '\r' && --eol == beg)
   981 			continue;
   982 		*eol = '\0';		// terminate line
   983 
   984 		while (isspace(*beg))
   985 			++beg;
   986 		char* comment = strchr(beg, '#');
   987 		if (comment)
   988 			eol = comment;
   989 		while (eol > beg && isspace(eol[-1]))
   990 			--eol;
   991 		if (beg == eol)
   992 			continue;
   993 		*eol = '\0';		// terminate line
   994 
   995 		TInt r = AddProperty(beg, eol);
   996 		if (r != KErrNone)
   997 			return r;
   998 		}
   999 	char sc[5];
  1000  	wsprintfA(sc, "%d", ScreenId+1);
  1001 	TInt screens;
  1002 	if(iProperties.GetInt("[screens]", screens) == KErrNone && screens > ScreenId)
  1003 		return KErrNone;
  1004  	else
  1005 		return iProperties.Replace("[screens]", sc)  == NULL ? KErrNoMemory : KErrNone;
  1006 	}
  1007 
  1008 TInt Wins::ReadIniFile(const char* aFileName, char*& aContents)
  1009 	{
  1010 	TInt r = KErrNone;
  1011 	HANDLE file=CreateFileA(aFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  1012 	if (!file || file==INVALID_HANDLE_VALUE)
  1013 		r = KErrNotFound;	// More than likely !
  1014 	else
  1015 		{
  1016 		TInt size=GetFileSize(file, NULL);
  1017 		if (size==INVALID_FILE_SIZE)
  1018 			r = KErrGeneral;
  1019 		else
  1020 			{
  1021 			// fileSize+3 to ensure zero-termination of file and trailing CRLF
  1022 			// VirtualAlloc initializes memory to zero
  1023 			TAny* data = VirtualAlloc(NULL, size+3, MEM_COMMIT, PAGE_READWRITE);
  1024 			if (!data)
  1025 				r = KErrNoMemory;
  1026 			else
  1027 				{
  1028 				DWORD bytesRead;
  1029 				if (!ReadFile(file, data, size, &bytesRead, NULL))
  1030 					{
  1031 					VirtualFree(data, 0, MEM_RELEASE);
  1032 					r = KErrGeneral;
  1033 					}
  1034 				else
  1035 					{
  1036 					aContents = (LPSTR)data;
  1037 					strcpy(aContents + size,"\r\n");
  1038 					}
  1039 				}
  1040 			}
  1041 		CloseHandle(file);
  1042 		}
  1043 	return r;
  1044 	}
  1045 
  1046 
  1047 TInt Wins::SetupPaths()
  1048 //
  1049 // set up the Emulator paths
  1050 //
  1051 	{
  1052 	// the Emulator path
  1053 	CHAR path[KMaxFileName + 1];
  1054 	DWORD len=GetModuleFileNameA(NULL, path, KMaxFileName);
  1055 	if (len == 0)
  1056 		return(KErrGeneral);
  1057 	path[len] = '\0';
  1058 	_strlwr(path);
  1059 	*(strrchr(path, '\\') + 1) = '\0';
  1060 	const char* emulatorPath = iProperties.Replace("EmulatorPath", path);
  1061 	if (!emulatorPath)
  1062 		return KErrNoMemory;
  1063 
  1064 	CHAR drive[KMaxFileName + 1];
  1065 
  1066 	// the Emulator data path
  1067 	strcat(path, "data\\");
  1068 	DWORD att = GetFileAttributesA(path);
  1069 	if (att != -1 && (att&FILE_ATTRIBUTE_DIRECTORY))
  1070 		{
  1071 		// if Data directory exists in the emulator path, do things the new way
  1072 		strcpy(drive, emulatorPath);
  1073 		strcat(drive,"c\\");
  1074 		}
  1075 	else
  1076 		{
  1077 		// the old way
  1078 #if defined(__VC32__)
  1079 		char* p = strstr(path, "\\epoc32\\release\\wins\\");
  1080 #elif defined(__CW32__)
  1081 		char* p = strstr(path, "\\epoc32\\release\\winscw\\");
  1082 #endif
  1083 		if (p == NULL)
  1084 			return KErrNotFound;
  1085 		strcpy(p, "\\epoc32\\");
  1086 		strcpy(drive, path);
  1087 		strcat(path, "data\\");
  1088 #if defined(__VC32__)
  1089 		strcat(drive,"wins\\c\\");
  1090 #elif defined(__CW32__)
  1091 		strcat(drive,"winscw\\c\\");
  1092 #endif
  1093 		}
  1094 	if (!iProperties.Replace("EmulatorDataPath", path))
  1095 		return KErrNoMemory;
  1096 
  1097 	// The Emulator Image path (for temporary EXE files)
  1098 	const char* eip;
  1099 	TInt r = iProperties.GetString("EmulatorImagePath", eip);
  1100 	if (r!=KErrNone)
  1101 		{
  1102 		len=GetTempPathA(KMaxFileName, path);
  1103 		strcat(path, "epoc\\");
  1104 		char* p = path + strlen(path);
  1105 		*p++ = emulatorPath[0];
  1106 		strcpy(p, emulatorPath+2);
  1107 		if (!iProperties.Replace("EmulatorImagePath", path))
  1108 			return KErrNoMemory;
  1109 		}
  1110 	else
  1111 		strcpy(path, eip);
  1112 	if (!Emulator::CreateAllDirectories(path))
  1113 		return Emulator::LastError();
  1114 
  1115 	// Win32 filesystem paths mapped to local WINS drives
  1116 	r = SetupDrive('c',drive);  // set up C here, can be overridden by system.ini settings
  1117 	if (r)
  1118 		return(r);
  1119 
  1120 	strcpy(drive, emulatorPath);
  1121 	strcat(drive,"z\\");
  1122 
  1123 	r=SetupDrive('z',drive);  // set up Z here, can be overridden by system.ini settings
  1124 	if (r)
  1125 		return(r);
  1126 
  1127 	return(KErrNone);
  1128 	}
  1129 
  1130 TInt Wins::SetupMediaPath()
  1131 //
  1132 // Set up the path for emulated media devices 'EmulatedMediaPath'
  1133 // The default is <datapath>media/
  1134 // The system temporary path can be set by value '%temp%'
  1135 //
  1136 	{
  1137 	CHAR path[KMaxFileName + 1];
  1138 	const char* mpath;
  1139 	if (iProperties.GetString("EmulatorMediaPath", mpath) == KErrNotFound)
  1140 		{
  1141 		const char* dpath;
  1142 		TInt r = iProperties.GetString("EmulatorDataPath", dpath);
  1143 		if (r != KErrNone)
  1144 			return r;
  1145 		strcpy(path, dpath);
  1146 		strcat(path, "media\\");
  1147 		return iProperties.Replace("EmulatorMediaPath", path) ? KErrNone : KErrNoMemory;
  1148 		}
  1149 
  1150 	if (_stricmp(mpath, "%temp%") == 0)
  1151 		{
  1152 		DWORD len=GetTempPathA(KMaxFileName, path);
  1153 		if (len > 0 && len < KMaxFileName)
  1154 			return iProperties.Replace("EmulatorMediaPath", path) ? KErrNone : KErrNoMemory;
  1155 		}
  1156 
  1157 	return KErrNone;
  1158 	}
  1159 
  1160 const char* Wins::EmulatorMediaPath()
  1161 	{
  1162 	const char* mpath = NULL;
  1163 	iProperties.GetString("EmulatorMediaPath", mpath);
  1164 	return mpath;
  1165 	}
  1166 
  1167 TInt Wins::SetupDrive(int aDrive, const char* aPath)
  1168 //
  1169 // set up emulated drives
  1170 //
  1171 	{
  1172 
  1173 	// Z drive can't end in anything but "Z\\", since we chop this off and use
  1174 	// the resulting directory to find filenames with no drive specified in
  1175 	// MapFileName() below.
  1176 	aDrive = tolower(aDrive);
  1177 	if (aDrive=='z')
  1178 		{
  1179 		const char* end = aPath + strlen(aPath);
  1180 		if (_stricmp(end-2,"\\z") != 0 && _stricmp(end-3,"\\z\\") != 0)
  1181 			return KErrArgument;
  1182 		}
  1183 
  1184 	char prop[] = "_epoc_drive_?";
  1185 	*strchr(prop, '?') = char(aDrive);
  1186 
  1187 
  1188     // If the path begins with the keyword %epocroot%, replace this with EPOCROOT
  1189     if (_strnicmp(aPath, "%epocroot%", 10) == 0)
  1190         {
  1191 		aPath += 10; // skip "%epocroot%"
  1192 
  1193         const char* eRoot;
  1194         TInt r = iProperties.GetString("EpocRoot", eRoot);
  1195         if (r != KErrNone)
  1196             return r;
  1197 
  1198 		int rootSize = strlen(eRoot);
  1199 		int pathSize = strlen(aPath);
  1200 		if(rootSize+pathSize>MAX_PATH)
  1201 			return KErrArgument;
  1202 
  1203         char fullPath[MAX_PATH+1];
  1204 		memcpy(fullPath,eRoot,rootSize);
  1205 		memcpy(fullPath+rootSize,aPath,pathSize+1); // +1 to get the terminating NULL char
  1206 
  1207         return iProperties.Replace(prop, fullPath) ? KErrNone : KErrNoMemory;
  1208 
  1209         }
  1210     else
  1211         // otherwise, aPath is fully qualified path name. Use that.
  1212         return iProperties.Replace(prop, aPath) ? KErrNone : KErrNoMemory;
  1213   
  1214 	}
  1215 
  1216 TInt Wins::MapDrive(int aDrive, TDes& aBuffer) const
  1217 //
  1218 // Map aDrive to a path given by environment variables or defaults
  1219 // Use this function only in WINS builds
  1220 //
  1221 	{
  1222 	char drive[KMaxFileName + 1];
  1223 	char prop[] = "_epoc_drive_?";
  1224 	*strchr(prop, '?') = char(tolower(aDrive));
  1225 
  1226 	TInt len;
  1227 	const char* val;
  1228 	if (iProperties.GetString(prop, val) == KErrNone)
  1229 		{
  1230 		len = strlen(val);
  1231 		if (len > KMaxFileName)
  1232 			return KErrArgument;
  1233 		strcpy(drive, val);
  1234 		}
  1235 	else
  1236 		{
  1237 		// not in properties, so check environment
  1238 		len = GetEnvironmentVariableA(prop, drive, KMaxFileName + 1);
  1239 		if (len > KMaxFileName)
  1240 			return KErrArgument;
  1241 		}
  1242 	while (len > 0 && isspace(drive[len-1]))
  1243 		--len;
  1244 	if (len == 0)
  1245 		return KErrNotFound;
  1246 	if (drive[len-1] != '\\') // add trailing backslash
  1247 		drive[len++] = '\\';
  1248 	if (drive[0] == '\\')
  1249 		{
  1250 		// put in the emulator drive
  1251 		TInt r = iProperties.GetString("EmulatorPath", val);
  1252 		if (r != KErrNone)
  1253 			return r;
  1254 
  1255 		memmove(drive + 2, drive, len);
  1256 		drive[0] = val[0];
  1257 		drive[1] = ':';
  1258 		len += 2;
  1259 		}
  1260 	else if (len < 3 || drive[1] != ':' || drive[2] != '\\')
  1261 		return KErrArgument;
  1262 #ifdef _UNICODE
  1263 	TUint16* aBufPtr = (TUint16*)aBuffer.Ptr();
  1264 	const TText* drv = (const TText*)drive;
  1265 	for(int index=0;index<len;index++)
  1266 		*aBufPtr++ = (TUint16)*drv++;
  1267 	aBuffer.SetLength(len<<1);
  1268 #else
  1269 	aBuffer.Copy(TPtrC8((const TText8*)drive,len));
  1270 #endif
  1271 	return KErrNone;
  1272 	}
  1273 
  1274 TInt Wins::MapFilename(const TDesC& aFilename, TDes& aBuffer) const
  1275 //
  1276 // Map aFileName to real windows directory - aFileName must be a full filepath
  1277 //
  1278 	{
  1279 
  1280 	// if the filename does not have a drive specified then don't imagine
  1281 	// it describes an Epoc filepath
  1282 	// Assume it's a subdirectory/file of the file containing the emulated Z drive
  1283 	TInt offset;
  1284 	if (aFilename.Length() < 4 || aFilename[2] != ':')
  1285 		{
  1286 		TInt r = MapDrive('z', aBuffer);
  1287 		if (r)
  1288 			return(r);
  1289 		aBuffer.SetLength(aBuffer.Length()-4);	// chop "Z\\"
  1290 		offset = aFilename[0] == '\\' ? 1 : 0; // remove the guaranteed backslash
  1291 		}
  1292 	else
  1293 		{
  1294 		TInt r = MapDrive(aFilename[0], aBuffer);
  1295 		if (r)
  1296 			return(r);
  1297 		if (aFilename.Length() >= 6 && aFilename[4] == '\\')
  1298 			offset = 3;
  1299 		else
  1300 			offset = 2;
  1301 		}
  1302 #ifdef _UNICODE
  1303 	offset = offset<<1;
  1304 	TUint8* ptrFilename = (TUint8*)aFilename.Ptr() + offset;
  1305 	TUint8* ptrBuffer = (TUint8*)aBuffer.Ptr()+aBuffer.Length();
  1306 	if (aBuffer.MaxLength()<aBuffer.Length()+aFilename.Length()-offset+1)
  1307 		return KErrBadName;
  1308 
  1309 	memcpy(ptrBuffer, ptrFilename, aFilename.Length()-offset);
  1310 	aBuffer.SetLength(aBuffer.Length()+aFilename.Length()-offset);
  1311 #else
  1312 	TPtrC name(aFilename.Mid(offset));
  1313 	if (aBuffer.MaxLength()<aBuffer.Length()+name.Length()+1)
  1314 		return KErrBadName;
  1315 	aBuffer.Append(name);
  1316 #endif
  1317 	return KErrNone;
  1318 	}
  1319 
  1320 
  1321 //table of the property names which can be used in multiple configurations
  1322 const char * KConfigSpecificProperties[] =
  1323 	{
  1324 	"ScreenWidth",
  1325 	"ScreenHeight",
  1326 	"PhysicalScreenWidth",
  1327 	"PhysicalScreenHeight",
  1328 	"ScreenOffsetX",
  1329 	"ScreenOffsetY",
  1330 	"LedSize",
  1331 	"LedArrangeVertically",
  1332 	"LedArrangeHorizontally",
  1333 	"LedOffsetX",
  1334 	"LedOffsetY",
  1335 	"LedGap",
  1336 	"PointerType",
  1337 	"ColorDepth",
  1338 	"KeyMap",
  1339 	"DrawVirtualKeys",
  1340 	"VirtualKeyColor",
  1341 	"VirtualKey",
  1342 	"MouseTarget",
  1343 	"FasciaBitmap",
  1344 	"DigitizerOffsetX",
  1345 	"DigitizerOffsetY",
  1346 	"DigitizerWidth",
  1347 	"DigitizerHeight",
  1348 	"DisableDigitizer",
  1349 	"DefineKeyName",
  1350 	"WindowTitle",
  1351 	"NoVersionInfo",
  1352 	"OnActivation",
  1353 	"EmulatorControl",
  1354 	"EmulatorControlHotKey",
  1355 	"CompositionBuffers",
  1356 	"RefreshRateHz",
  1357 	};
  1358 
  1359 const char * KScreenSpecificProperties[] =
  1360  	{
  1361  	"ScreenWidth",
  1362  	"ScreenHeight",
  1363  	"PhysicalScreenWidth",
  1364  	"PhysicalScreenHeight",
  1365  	"ScreenOffsetX",
  1366  	"ScreenOffsetY",
  1367  	"ColorDepth",
  1368 	"FasciaBitmap",
  1369 	"CompositionBuffers",
  1370 	"RefreshRateHz",
  1371  	};
  1372 
  1373 
  1374 TBool Wins::ConfigSpecificProperty(const char * aProperty)
  1375 	{
  1376 	TInt x;
  1377 	TInt count = sizeof(KConfigSpecificProperties) / sizeof(char *);
  1378 	for (x = 0; x < count; ++x)
  1379 		if (_stricmp(aProperty, KConfigSpecificProperties[x]) == 0)	return ETrue;
  1380 	return EFalse;
  1381 	}
  1382 
  1383 TBool Wins::ScreenSpecificProperty(const char * aProperty)
  1384 	{
  1385 	TInt x;
  1386 	TInt count = sizeof(KScreenSpecificProperties) / sizeof(char *);
  1387 	for (x = 0; x < count; ++x)
  1388 		if (_stricmp(aProperty, KScreenSpecificProperties[x]) == 0)	return ETrue;
  1389 	return EFalse;
  1390 	}