os/kernelhwsrv/kernel/eka/euser/epoc/win32/emulator.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200 (2014-06-10)
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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 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 #define _CRTIMP			// we want to use the static runtime library
    17 #include <e32cmn.h>
    18 #include <e32cmn_private.h>
    19 #include <string.h>
    20 #include <emulator.h>
    21 #include <e32ldr.h>
    22 #include <e32ldr_private.h>
    23 #include <e32uid.h>
    24 
    25 #pragma data_seg(".data2")
    26 #ifdef __VC32__
    27 #pragma bss_seg(".data2")
    28 #endif
    29 static TBool UnicodeHost;
    30 static Emulator::SInit Data;
    31 #pragma data_seg()
    32 #ifdef __VC32__
    33 #pragma bss_seg()
    34 #endif
    35 
    36 /**	
    37 Initializes a module and prepares it to handle requests.
    38 
    39 @param aInit	An object of the structure SInit.
    40 
    41 @see SInit.
    42 */
    43 EXPORT_C void Emulator::Init(const Emulator::SInit& aInit)
    44 	{
    45 	UnicodeHost = (GetVersion() & 0x80000000) ? FALSE : TRUE;
    46 	Data = aInit;
    47 	if (Data.iCodePage == 0)
    48 		Data.iCodePage = CP_ACP;
    49 	}
    50 
    51 LOCAL_C DWORD UStringLength(LPCSTR lpMultiByteStr)
    52 //
    53 // returns length of unicode string generated - assumes null terminated string
    54 //
    55 	{
    56 	return MultiByteToWideChar(Data.iCodePage,0,lpMultiByteStr,-1,0,0);
    57 	}
    58 
    59 
    60 LOCAL_C DWORD ConvertToUnicode(LPCSTR aNarrow,LPWSTR aUnicode,DWORD aLength,BOOL aCharsRequired)
    61 //
    62 // Converts narrow string to unicode string
    63 //
    64 	{
    65 	DWORD uniLength=UStringLength(aNarrow);
    66 	if(uniLength>aLength || uniLength==0)
    67 		return aCharsRequired ? uniLength : 0;
    68 	uniLength=MultiByteToWideChar(Data.iCodePage,0,aNarrow,-1,aUnicode,aLength);
    69 	// return number of characters excluding the null terminator
    70 	return uniLength ? uniLength-1 : 0;
    71 	}
    72 
    73 
    74 LOCAL_C DWORD ConvertToNarrow(LPCWSTR aUnicode,LPSTR aNarrow,DWORD aLength)
    75 //
    76 // Converts unicode string to narrow string
    77 //
    78 	{
    79 	return WideCharToMultiByte(Data.iCodePage,0,aUnicode,-1,aNarrow,aLength,"@",NULL);
    80 	}
    81 
    82 template <TUint S>
    83 struct Buf8
    84 	{
    85 public:
    86 	Buf8(LPCWSTR aUnicode);
    87 	inline operator LPCSTR() const
    88 		{return iPtr;}
    89 private:
    90 	const char* iPtr;
    91 	char iBuf[S];
    92 	};
    93 
    94 template <TUint S>
    95 Buf8<S>::Buf8(LPCWSTR aUnicode)
    96 	{
    97 	if (aUnicode)
    98 		{
    99 		iPtr = iBuf;
   100 		ConvertToNarrow(aUnicode,iBuf,S);
   101 		}
   102 	else
   103 		{
   104 		iPtr = NULL;
   105 		}
   106 	}
   107 
   108 
   109 
   110 /**	
   111 Acquires the global lock for host interaction.
   112 */
   113 EXPORT_C void Emulator::Lock()
   114 	{
   115 	Data.iLock();
   116 	}
   117 
   118 /**
   119 Releases the global lock for host interaction.
   120 This may overwrite the error code for this thread and that is not the behaviour expected, 
   121 so save and restore it.
   122 */
   123 EXPORT_C void Emulator::Unlock()
   124 	{
   125 	DWORD error=GetLastError();
   126 	Data.iUnlock();
   127 	SetLastError(error);
   128 	}
   129 
   130 /**
   131 Takes the current thread out of the emulator scheduling model.
   132 */
   133 EXPORT_C void Emulator::Escape()
   134 	{
   135 	Data.iEscape();
   136 	}
   137 
   138 /**
   139 Returns the calling thread into the emulator scheduling model.
   140 This may overwrite the error code for this thread and that is not the behaviour expected, 
   141 so save and restore it.
   142 */
   143 EXPORT_C void Emulator::Reenter()
   144 	{
   145 	DWORD error=GetLastError();
   146 	Data.iReenter();
   147 	SetLastError(error);
   148 	}
   149 
   150 
   151 /**
   152 Jumps to the NThread Win32 SEH exception handler.
   153 
   154 @param aException	Describes an exception.
   155 @param aContext		Describes the context.
   156 	
   157 @return   A handler to handle the exception occurred
   158 */
   159 EXPORT_C DWORD Emulator::Win32SEHException(EXCEPTION_RECORD* aException, CONTEXT* aContext)
   160 	{
   161 	return Data.iException(aException, aContext);
   162 	}
   163 
   164 
   165 /**
   166 This function wraps the Win32 CreateDirectory API (see http://msdn2.microsoft.com/en-us/library/aa363855.aspx).
   167 */  
   168 EXPORT_C BOOL Emulator::CreateDirectory(LPCWSTR lpPathName,LPSECURITY_ATTRIBUTES lpSecurityAttributes)
   169 	{
   170 	__LOCK_HOST;
   171 
   172 	if (UnicodeHost)
   173 		return ::CreateDirectoryW(lpPathName, lpSecurityAttributes);
   174 
   175 	return ::CreateDirectoryA(Buf8<MAX_PATH>(lpPathName),lpSecurityAttributes);
   176 	}
   177 
   178 #ifdef __VC32__
   179 //disable unreachable code warning in VC++
   180 #pragma warning (disable : 4702)
   181 #endif
   182 
   183 
   184 /**
   185 Recursively ensures that the full directory exists.
   186 	
   187 @param aPathName  	Provides the path name.
   188 
   189 @return  TRUE, if the function succeeds
   190 		 FALSE, if the function fails
   191 */
   192 EXPORT_C BOOL Emulator::CreateAllDirectories(LPCSTR aPathName)
   193 	{
   194 	__LOCK_HOST;
   195 
   196 	char path[MAX_PATH];
   197 	strcpy(path, aPathName);
   198 	char* p = path;
   199 	for (;;)
   200 		{
   201 		p = strchr(p, '\\');
   202 		char temp=0;
   203 		if (p)
   204 			{
   205 			temp = *++p;
   206 			*p = '\0';
   207 			}
   208 		DWORD att = ::GetFileAttributesA(path);
   209 		if ((att == -1 || !(att&FILE_ATTRIBUTE_DIRECTORY)) && !::CreateDirectoryA(path, NULL))
   210 			return EFalse;
   211 		if (!p)
   212 			return ETrue;
   213 		*p = temp;
   214 		}
   215 	}
   216 #ifdef __VC32__
   217 //enable unreachable code warning in VC++
   218 #pragma warning (default : 4702)
   219 #endif
   220 
   221 #ifndef INVALID_FILE_ATTRIBUTES	
   222 #define INVALID_FILE_ATTRIBUTES	 ((DWORD)-1)
   223 #endif
   224 
   225 
   226 /**
   227 This function wraps the Win32 CreateFile API (see http://msdn2.microsoft.com/en-us/library/aa363858.aspx).
   228 It also modifies file attributes depending on whether the file is hidden or not.
   229 */
   230 EXPORT_C HANDLE Emulator::CreateFile(LPCWSTR lpFileName,DWORD dwDesiredAccess,DWORD dwShareMode,
   231 						   LPSECURITY_ATTRIBUTES lpSecurityAttributes,DWORD dwCreationDistribution,
   232 						   DWORD dwFlagsAndAttributes,HANDLE hTemplateFile)
   233 	{
   234 	__LOCK_HOST;
   235 	HANDLE h;
   236 	BOOL hidden = 0; 
   237 	DWORD att = INVALID_FILE_ATTRIBUTES;
   238 	if(dwCreationDistribution==CREATE_ALWAYS)
   239 		{
   240 		att = ::GetFileAttributes(lpFileName);
   241 		if(att!=INVALID_FILE_ATTRIBUTES && (att&FILE_ATTRIBUTE_HIDDEN))
   242 			{
   243 			hidden = ::SetFileAttributes(lpFileName, (att&~FILE_ATTRIBUTE_HIDDEN));
   244 			}
   245 		}
   246 		
   247 	if (UnicodeHost)
   248 		h = ::CreateFileW(lpFileName,dwDesiredAccess,dwShareMode,lpSecurityAttributes,dwCreationDistribution,
   249 							dwFlagsAndAttributes,hTemplateFile);
   250 	else
   251 		h = ::CreateFileA(Buf8<MAX_PATH>(lpFileName),dwDesiredAccess,dwShareMode,lpSecurityAttributes,dwCreationDistribution,
   252 						dwFlagsAndAttributes,hTemplateFile);
   253 	
   254 	if(hidden && h!=INVALID_HANDLE_VALUE)
   255 		{
   256 		::SetFileAttributes(lpFileName, att);
   257 		}
   258 	return h;
   259 	}
   260 
   261 
   262 /**
   263 This function wraps the Win32 DeleteFile API (see http://msdn2.microsoft.com/en-us/library/aa363915.aspx).
   264 */
   265 EXPORT_C BOOL Emulator::DeleteFile(LPCWSTR lpFileName)
   266 	{
   267 	__LOCK_HOST;
   268 
   269 	if (UnicodeHost)
   270 		return ::DeleteFileW(lpFileName);
   271 
   272 	return ::DeleteFileA(Buf8<MAX_PATH>(lpFileName));
   273 	}
   274 
   275 LOCAL_C TBool MapFindFileData(LPWIN32_FIND_DATAW lpFindFileData, LPWIN32_FIND_DATAA lpFindNarrow)
   276 	{
   277 	lpFindFileData->dwFileAttributes=lpFindNarrow->dwFileAttributes;
   278 	lpFindFileData->ftCreationTime=lpFindNarrow->ftCreationTime;
   279 	lpFindFileData->ftLastAccessTime=lpFindNarrow->ftLastAccessTime;
   280 	lpFindFileData->ftLastWriteTime=lpFindNarrow->ftLastWriteTime;
   281 	lpFindFileData->nFileSizeHigh=lpFindNarrow->nFileSizeHigh;
   282 	lpFindFileData->nFileSizeLow=lpFindNarrow->nFileSizeLow;
   283 	
   284 	if(!MultiByteToWideChar(Data.iCodePage,0,lpFindNarrow->cFileName,-1,lpFindFileData->cFileName,MAX_PATH))
   285 		return FALSE;
   286 
   287 	if(lpFindNarrow->cAlternateFileName!=NULL)
   288 		{
   289 		// magic number 14 comes from MS documentation
   290 		if(!MultiByteToWideChar(Data.iCodePage,0,lpFindNarrow->cAlternateFileName,-1,lpFindFileData->cAlternateFileName,14))
   291 			return FALSE;
   292 		}
   293 	return TRUE;
   294 	}
   295 
   296 
   297 /**
   298 This function wraps the Win32 FindFirstFile API (see http://msdn2.microsoft.com/en-us/library/aa364418.aspx).	
   299 */
   300 EXPORT_C HANDLE Emulator::FindFirstFile(LPCWSTR lpFileName,LPWIN32_FIND_DATAW lpFindFileData)
   301 	{
   302 	__LOCK_HOST;
   303 
   304 	if (UnicodeHost)
   305 		return ::FindFirstFileW(lpFileName, lpFindFileData);
   306 
   307 	WIN32_FIND_DATAA lpFindNarrow;
   308 	HANDLE h=::FindFirstFileA(Buf8<MAX_PATH>(lpFileName),&lpFindNarrow);
   309 	if(h==INVALID_HANDLE_VALUE)
   310 		return h;
   311 
   312 	if (!MapFindFileData(lpFindFileData, &lpFindNarrow))
   313 		{
   314 		FindClose(h);
   315 		return INVALID_HANDLE_VALUE;
   316 		}
   317 
   318 	return h;
   319 	}
   320 
   321 
   322 /**
   323 This function wraps the Win32 FindNextFile API (see http://msdn2.microsoft.com/en-us/library/aa364428.aspx).	
   324 */
   325 EXPORT_C BOOL Emulator::FindNextFile(HANDLE hFindFile,LPWIN32_FIND_DATAW lpFindFileData)
   326 	{
   327 	__LOCK_HOST;
   328 
   329 	if (UnicodeHost)
   330 		return ::FindNextFileW(hFindFile, lpFindFileData);
   331 
   332 	WIN32_FIND_DATAA lpFindNarrow;
   333 	if(!::FindNextFileA(hFindFile,&lpFindNarrow))
   334 		return FALSE;
   335 
   336 	return MapFindFileData(lpFindFileData, &lpFindNarrow);
   337 	}
   338 
   339 /**
   340 This function wraps the Win32 GetDiskFreeSpace API (see http://msdn2.microsoft.com/en-us/library/aa364935.aspx).
   341 */
   342 EXPORT_C BOOL Emulator::GetDiskFreeSpace(LPCWSTR lpRootPathName,LPDWORD lpSectorsPerCluster,\
   343 							   LPDWORD lpBytesPerSector,LPDWORD lpNumberOfFreeClusters,\
   344 							   LPDWORD lpTotalNumberOfClusters)
   345 	{
   346 	__LOCK_HOST;
   347 
   348 	if (UnicodeHost)
   349 		return ::GetDiskFreeSpaceW(lpRootPathName,lpSectorsPerCluster,lpBytesPerSector,lpNumberOfFreeClusters,lpTotalNumberOfClusters);
   350 
   351 	return ::GetDiskFreeSpaceA(Buf8<MAX_PATH>(lpRootPathName),lpSectorsPerCluster,lpBytesPerSector,lpNumberOfFreeClusters,lpTotalNumberOfClusters);
   352 
   353 	}
   354 
   355 
   356 /**
   357 This function wraps the Win32 GetFileAttributes API (see http://msdn2.microsoft.com/en-us/library/aa364944.aspx).
   358 */
   359 EXPORT_C DWORD Emulator::GetFileAttributes(LPCWSTR lpFileName)
   360 	{
   361 	__LOCK_HOST;
   362 
   363 	if (UnicodeHost)
   364 		return ::GetFileAttributesW(lpFileName);
   365 
   366 	return ::GetFileAttributesA(Buf8<MAX_PATH>(lpFileName));
   367 	}
   368 
   369 
   370 /**
   371 This function wraps the Win32 GetModuleHandle API (see http://msdn2.microsoft.com/en-us/library/ms683199.aspx).
   372 */
   373 EXPORT_C HMODULE Emulator::GetModuleHandle(LPCWSTR lpModuleName)
   374 	{
   375 	__LOCK_HOST;
   376 
   377 	if (UnicodeHost)
   378 		return ::GetModuleHandleW(lpModuleName);
   379 
   380 	return ::GetModuleHandleA(Buf8<MAX_PATH>(lpModuleName));
   381 	}
   382 
   383 
   384 /**
   385 This function wraps the Win32 GetModuleFileName API (see http://msdn2.microsoft.com/en-us/library/ms683197.aspx).
   386 */
   387 EXPORT_C DWORD Emulator::GetModuleFileName(HMODULE hModule, LPWSTR lpFilename)
   388 	{
   389 	__LOCK_HOST;
   390 	if (UnicodeHost)
   391 		return ::GetModuleFileNameW(hModule, lpFilename, MAX_PATH);
   392 	char fn[MAX_PATH];
   393 	DWORD r=::GetModuleFileNameA(hModule, fn, MAX_PATH);
   394 	if (r>MAX_PATH||r==0)
   395 		return 0;
   396 	return ConvertToUnicode(fn, lpFilename, MAX_PATH, TRUE);
   397 	}
   398 
   399 
   400 /**
   401 This function wraps the Win32 GetTempPath API (see http://msdn2.microsoft.com/en-us/library/Aa364992.aspx).
   402 */
   403 EXPORT_C DWORD Emulator::GetTempPath(DWORD nBufferLength,LPWSTR lpBuff)
   404 	{
   405 	__LOCK_HOST;
   406 
   407 	if (UnicodeHost)
   408 		return ::GetTempPathW(nBufferLength,lpBuff);
   409 
   410 	char path[MAX_PATH];
   411 	DWORD r=::GetTempPathA(MAX_PATH,path);
   412 	if(r>MAX_PATH||r==0)
   413 		return 0;
   414 	return ConvertToUnicode(path,lpBuff,nBufferLength,TRUE);
   415 	}
   416 
   417 
   418 /**
   419 This function wraps the Win32 GetCurrentDirectory API (see http://msdn2.microsoft.com/en-us/library/aa364934.aspx).
   420 */
   421 EXPORT_C DWORD Emulator::GetCurrentDirectory(DWORD nBufferLength,LPWSTR lpBuff)
   422 	{
   423 	__LOCK_HOST;
   424 
   425 	if (UnicodeHost)
   426 		return ::GetCurrentDirectoryW(nBufferLength,lpBuff);
   427 
   428 	char path[MAX_PATH];
   429 	DWORD r=::GetCurrentDirectoryA(MAX_PATH,path);
   430 	if(r>MAX_PATH||r==0)
   431 		return 0;
   432 	return ConvertToUnicode(path,lpBuff,nBufferLength,TRUE);
   433 	}
   434 
   435 
   436 /**
   437 This function wraps the Win32 GetVolumeInformation API (see http://msdn2.microsoft.com/en-us/library/aa364993.aspx).
   438 */
   439 EXPORT_C BOOL Emulator::GetVolumeInformation(LPCWSTR lpRootPathName,LPWSTR lpVolumeNameBuffer,DWORD nVolumeNameSize,
   440 								   LPDWORD lpVolumeSerialNumber,LPDWORD lpMaximumComponentLength,
   441 								   LPDWORD lpFileSystemFlags,LPWSTR,DWORD)
   442 	{
   443 	__LOCK_HOST;
   444 
   445 	// lpfileSystemNameBuffer always NULL so no need to convert
   446 	if (UnicodeHost)
   447 		return ::GetVolumeInformationW(lpRootPathName,lpVolumeNameBuffer,nVolumeNameSize,lpVolumeSerialNumber,
   448 										lpMaximumComponentLength,lpFileSystemFlags,NULL,0);
   449 
   450 	char volName[MAX_PATH];
   451 	BOOL res=::GetVolumeInformationA(Buf8<MAX_PATH>(lpRootPathName),volName,MAX_PATH,lpVolumeSerialNumber,
   452 									lpMaximumComponentLength,lpFileSystemFlags,NULL,0);
   453 
   454 	if(res && lpVolumeNameBuffer)
   455 		ConvertToUnicode(volName,lpVolumeNameBuffer,nVolumeNameSize,FALSE);
   456 	return res;
   457 	}
   458 
   459 
   460 /**
   461 This function wraps the Win32 LoadLibrary API (see http://msdn2.microsoft.com/en-us/library/ms684175.aspx).
   462 */
   463 EXPORT_C HMODULE Emulator::LoadLibrary(LPCWSTR lpLibFileName)
   464 	{
   465 	__LOCK_HOST;
   466 
   467 	if (UnicodeHost)
   468 		return ::LoadLibraryW(lpLibFileName);
   469 
   470 	return ::LoadLibraryA(Buf8<MAX_PATH>(lpLibFileName));
   471 	}
   472 
   473 
   474 /**
   475 This function wraps the Win32 FreeLibrary API (see http://msdn2.microsoft.com/en-us/library/ms683152.aspx).
   476 */
   477 EXPORT_C BOOL Emulator::FreeLibrary(HMODULE hLibModule)
   478 	{
   479 	__LOCK_HOST;
   480 	return ::FreeLibrary(hLibModule);
   481 	}
   482 
   483 
   484 
   485 /**
   486 This function wraps the Win32 MoveFile API (see http://msdn2.microsoft.com/en-us/library/aa365239.aspx).
   487 */
   488 EXPORT_C BOOL Emulator::MoveFile(LPCWSTR lpExistingFileName,LPCWSTR lpNewFileName)
   489 	{
   490 	__LOCK_HOST;
   491 
   492 	if (UnicodeHost)
   493 		return ::MoveFileW(lpExistingFileName,lpNewFileName);
   494 
   495 	return ::MoveFileA(Buf8<MAX_PATH>(lpExistingFileName),Buf8<MAX_PATH>(lpNewFileName));
   496 	}
   497 
   498 
   499 /**
   500 This function wraps the Win32 CopyFile API (see http://msdn2.microsoft.com/en-us/library/aa363851.aspx).
   501 */
   502 EXPORT_C BOOL Emulator::CopyFile(LPCWSTR lpExistingFileName,LPCWSTR lpNewFileName,BOOL aFailIfExists)
   503 	{
   504 	__LOCK_HOST;
   505 
   506 	if (UnicodeHost)
   507 		return ::CopyFileW(lpExistingFileName,lpNewFileName,aFailIfExists);
   508 
   509 	return ::CopyFileA(Buf8<MAX_PATH>(lpExistingFileName),Buf8<MAX_PATH>(lpNewFileName),aFailIfExists);
   510 	}
   511 
   512 
   513 /**
   514 This function wraps the Win32 OutputDebugString API (see http://msdn2.microsoft.com/en-us/library/aa363362.aspx).
   515 */
   516 EXPORT_C VOID Emulator::OutputDebugString(LPCWSTR lpOutputString)
   517 	{
   518 	if (UnicodeHost)
   519 		::OutputDebugStringW(lpOutputString);
   520 	else
   521 		::OutputDebugStringA(Buf8<1024>(lpOutputString));
   522 	}
   523 
   524 
   525 
   526 /**
   527 This function wraps the Win32 RemoveDirectory API (see http://msdn2.microsoft.com/en-us/library/aa365488.aspx).
   528 */
   529 EXPORT_C BOOL Emulator::RemoveDirectory(LPCWSTR lpPathName)
   530 	{
   531 	__LOCK_HOST;
   532 
   533 	if (UnicodeHost)
   534 		return ::RemoveDirectoryW(lpPathName);
   535 
   536 	return ::RemoveDirectoryA(Buf8<MAX_PATH>(lpPathName));
   537 	}
   538 
   539 
   540 /**
   541 This function wraps the Win32 SetFileAttributes API (see http://msdn2.microsoft.com/en-us/library/aa365535.aspx).
   542 */
   543 
   544 EXPORT_C BOOL Emulator::SetFileAttributes(LPCWSTR lpFileName,DWORD dwFileAttributes)
   545 	{
   546 	__LOCK_HOST;
   547 
   548 	if (UnicodeHost)
   549 		return ::SetFileAttributesW(lpFileName,dwFileAttributes);
   550 
   551 	return ::SetFileAttributesA(Buf8<MAX_PATH>(lpFileName),dwFileAttributes);
   552 	}
   553 
   554 
   555 
   556 /**
   557 This function wraps the Win32 SetVolumeLabel API (see http://msdn2.microsoft.com/en-us/library/aa365560.aspx).
   558 */
   559 EXPORT_C BOOL Emulator::SetVolumeLabel(LPCWSTR lpRootPathName,LPCWSTR lpVolumeName)
   560 	{
   561 	__LOCK_HOST;
   562 
   563 	if (UnicodeHost)
   564 		return ::SetVolumeLabelW(lpRootPathName,lpVolumeName);
   565 
   566 	return ::SetVolumeLabelA(Buf8<MAX_PATH>(lpRootPathName),Buf8<MAX_PATH>(lpVolumeName));
   567 	}
   568 
   569 
   570 /**
   571 Maps an NT error to an Epoc32 error.
   572 	
   573 @return	 Last-error code of the calling thread.
   574 */
   575 EXPORT_C TInt Emulator::LastError()
   576 
   577 // For other error codes look at MSDN "Numerical List of Error Codes"
   578 	{
   579 	switch (GetLastError())
   580 		{
   581 	case ERROR_SUCCESS:				return KErrNone;
   582 	case ERROR_INVALID_DRIVE:		return KErrNotReady;
   583 	case ERROR_INVALID_NAME:
   584 	case ERROR_FILENAME_EXCED_RANGE:
   585 	case ERROR_OPEN_FAILED:			return KErrBadName; 
   586 	case ERROR_INVALID_HANDLE:		return KErrBadHandle;
   587 	case ERROR_NOT_SUPPORTED:
   588 	case ERROR_INVALID_FUNCTION:	return KErrNotSupported;
   589 	case ERROR_SHARING_VIOLATION: 
   590 	case ERROR_ACCESS_DENIED: 
   591 	case ERROR_WRITE_PROTECT:		return KErrAccessDenied;
   592 	case ERROR_LOCK_VIOLATION:		return KErrLocked;
   593 	case ERROR_FILE_NOT_FOUND:
   594 	case ERROR_MOD_NOT_FOUND:		return KErrNotFound;
   595 	case ERROR_DIRECTORY: 
   596 	case ERROR_BAD_PATHNAME:
   597 	case ERROR_PATH_NOT_FOUND:		return KErrPathNotFound; 
   598 	case ERROR_ALREADY_EXISTS:
   599 	case ERROR_FILE_EXISTS:			return KErrAlreadyExists;
   600 	case ERROR_NOT_READY:			return KErrNotReady; 
   601 	case ERROR_UNRECOGNIZED_VOLUME:
   602 	case ERROR_NOT_DOS_DISK:		return KErrUnknown;
   603 	case ERROR_UNRECOGNIZED_MEDIA:
   604 	case ERROR_BAD_EXE_FORMAT:		return KErrCorrupt;
   605 	case ERROR_NO_MORE_FILES:		return KErrEof; 
   606 	case ERROR_DIR_NOT_EMPTY:		return KErrInUse;
   607 	case ERROR_INVALID_USER_BUFFER:
   608 	case ERROR_NOT_ENOUGH_MEMORY:
   609 	case ERROR_INSUFFICIENT_BUFFER:
   610 	case ERROR_OUTOFMEMORY:			return KErrNoMemory;
   611 	case ERROR_DISK_FULL:			return KErrDiskFull;
   612 	case ERROR_INVALID_DATA:
   613 	case ERROR_INVALID_PARAMETER:	return KErrArgument;
   614 	case ERROR_OPERATION_ABORTED:	return KErrCancel;
   615 
   616     default:						return KErrGeneral;
   617 		}
   618 	}
   619 
   620 /**
   621 This function wraps the Win32 GetProcAddress API (see http://msdn2.microsoft.com/en-us/library/ms683212.aspx).
   622 */
   623 FARPROC Emulator::GetProcAddress(HMODULE hModule, LPCSTR lpProcName)
   624 	{
   625 	__LOCK_HOST;
   626 	return ::GetProcAddress(hModule, lpProcName);
   627 	}
   628 
   629 
   630 
   631 // image file support
   632 
   633 // loaded modules
   634 
   635 
   636 /**
   637 Gets the header format of the file system.
   638 
   639 @return		Returns the header format of the file system.	
   640 */
   641 EXPORT_C const IMAGE_NT_HEADERS32* Emulator::TModule::NtHeader() const
   642 	{
   643 	if (!IsValid())
   644 		return 0;
   645 	const IMAGE_DOS_HEADER* dhead = (const IMAGE_DOS_HEADER*)Translate(0);
   646 	if ( IMAGE_DOS_SIGNATURE != dhead->e_magic )
   647 		return 0;
   648 	if (dhead->e_lfarlc < sizeof(IMAGE_DOS_HEADER))
   649 		return 0;
   650 	const IMAGE_NT_HEADERS32* ntHead = (const IMAGE_NT_HEADERS32*)Translate(dhead->e_lfanew);
   651     if ( ntHead->Signature != IMAGE_NT_SIGNATURE )
   652 		return 0;
   653 	return ntHead;
   654 	}
   655 
   656 
   657 /**
   658 Constructor which sets the handles of loaded module to the specified module.
   659 
   660 @param aModuleName		Holds the name of the module to be loaded.
   661 */
   662 EXPORT_C Emulator::TModule::TModule(LPCSTR aModuleName)
   663 	: iModule(GetModuleHandleA(aModuleName)), iBase(iModule)
   664 	{
   665 	if (!NtHeader())
   666 		{
   667 		iModule = 0;
   668 		iBase = 0;
   669 		}
   670 	}
   671 
   672 
   673 /**
   674 Gets the pointer of the section header if the header name matches with the buffer aSection[].
   675 		
   676 @param aSection[]	A buffer of type BYTE.		
   677 
   678 @return 	Returns the pointer to section header of the file system.
   679 */
   680 EXPORT_C const IMAGE_SECTION_HEADER* Emulator::TModule::SectionHeader(const BYTE aSection[]) const
   681 	{
   682 	const IMAGE_NT_HEADERS32* ntHead = NtHeader();
   683 	if (!ntHead)
   684 		return 0;
   685 
   686 	const IMAGE_SECTION_HEADER* imgHead = (const IMAGE_SECTION_HEADER*)((TUint8*)&ntHead->OptionalHeader + ntHead->FileHeader.SizeOfOptionalHeader);
   687 	const IMAGE_SECTION_HEADER* end = imgHead + ntHead->FileHeader.NumberOfSections;
   688 	for (; imgHead < end; ++imgHead)
   689 		{
   690 		if (memcmp(imgHead->Name, aSection, IMAGE_SIZEOF_SHORT_NAME)==0)
   691 			return imgHead;
   692 		}
   693 	return 0;
   694 	}
   695 
   696 
   697 /**
   698 Points to the first byte or first page of the loaded module or mapped file image.
   699 		
   700 @param aSection[]	A buffer of type BYTE.
   701 		
   702 @return TAny		Returns first byte of the loaded module or first page of the mapped file image.
   703 */
   704 EXPORT_C const TAny* Emulator::TModule::Section(const BYTE aSection[]) const
   705 	{
   706 	const IMAGE_SECTION_HEADER* imgHead = SectionHeader(aSection);
   707 	if (imgHead)
   708 		return Translate(IsLoaded() ? imgHead->VirtualAddress : imgHead->PointerToRawData);
   709 	return 0;
   710 	}
   711 
   712 
   713 /**
   714 Go through the section headers looking for UID section.
   715 	
   716 @param aType	Contains a UID type.
   717 */
   718 EXPORT_C void Emulator::TModule::GetUids(TUidType& aType) const
   719 	{
   720 	const TEmulatorImageHeader* hdr = (const TEmulatorImageHeader*)Section(KWin32SectionName_Symbian);
   721 	if (hdr)
   722 		aType = *(const TUidType*)&hdr->iUids[0];
   723 	}
   724 
   725 
   726 /**
   727 Goes through section headers and gets the information of file system.
   728 
   729 @param aInfo	Contains the information of the file system.
   730 */
   731 EXPORT_C void Emulator::TModule::GetInfo(TProcessCreateInfo& aInfo) const
   732 	{
   733 	aInfo.iExceptionDescriptor = 0;
   734 	const IMAGE_NT_HEADERS32* ntHead = NtHeader();
   735 	if (ntHead)
   736 		{
   737 		const TEmulatorImageHeader* hdr = (const TEmulatorImageHeader*)Section(KWin32SectionName_Symbian);
   738 		if (hdr)
   739 			{
   740 			aInfo.iUids = *(const TUidType*)&hdr->iUids[0];
   741 			TBool isExe = (hdr->iUids[0].iUid==KExecutableImageUidValue);
   742 			TBool data_section_present = (Section(KWin32SectionName_EpocData)!=NULL);
   743 			TBool data = hdr->iFlags & KEmulatorImageFlagAllowDllData;
   744 			if (data_section_present && isExe)
   745 				data = ETrue;
   746 			aInfo.iBssSize=data?1:0;
   747 			aInfo.iDataSize=0;
   748 			aInfo.iTotalDataSize=aInfo.iBssSize;
   749 			aInfo.iDepCount = 0;
   750 			aInfo.iHeapSizeMin = ntHead->OptionalHeader.SizeOfHeapCommit;
   751 			aInfo.iHeapSizeMax = ntHead->OptionalHeader.SizeOfHeapReserve;
   752 			aInfo.iStackSize = 0x1000;
   753 			aInfo.iPriority = hdr->iPriority;
   754 			aInfo.iHandle = NULL;
   755 			aInfo.iS = hdr->iS;
   756 			aInfo.iModuleVersion = hdr->iModuleVersion;
   757 			if (ntHead->FileHeader.Characteristics & IMAGE_FILE_DLL)
   758 				aInfo.iAttr |= ECodeSegAttHDll;
   759 			}
   760 		}
   761 	GetUids(aInfo.iUids);
   762 	}
   763 
   764 
   765 /**
   766 Finds the import section from the data directory. This relies on the module being loaded.
   767 		
   768 @return 	Returns the imported executable.
   769 */
   770 EXPORT_C const IMAGE_IMPORT_DESCRIPTOR* Emulator::TModule::Imports() const
   771 	{
   772 	if (!IsLoaded())
   773 		return NULL;
   774 	const IMAGE_NT_HEADERS32* ntHead = NtHeader();
   775 	if (!ntHead)
   776 		return NULL;
   777 	DWORD va = ntHead->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
   778 	if (!va)
   779 		return NULL;
   780 	return (const IMAGE_IMPORT_DESCRIPTOR*)Translate(va);
   781 	}
   782 
   783 // modules in the file system
   784 EXPORT_C TInt Emulator::RImageFile::Open(LPCTSTR aImageFile)
   785 	{
   786 	Buf8<MAX_PATH>   nameBuf(aImageFile);
   787 	char *pName = (char *)strrchr(LPCSTR(nameBuf), '\\');
   788 	pName ? ++pName : pName = (char *)LPCSTR(nameBuf);
   789 
   790 	__LOCK_HOST;
   791 	iMapping = OpenFileMapping(FILE_MAP_READ, FALSE, (LPCTSTR)pName);
   792 	if (!iMapping)
   793 		{
   794 		if (pName == (char *)LPCSTR(nameBuf))
   795 			iModule = Emulator::GetModuleHandle(aImageFile);
   796 		if (iModule)
   797 			iBase = iModule;
   798 		else
   799 			{
   800 			// need to map the file instead
   801 			HANDLE file = Emulator::CreateFile(aImageFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
   802 			if (file == INVALID_HANDLE_VALUE)
   803 				return LastError();
   804 			iMapping = CreateFileMappingA(file, NULL, PAGE_READONLY, 0, 0, pName);
   805 			CloseHandle(file);
   806 			}
   807 		}
   808 	if (!iModule)
   809 		{
   810 		if (!iMapping)
   811 			return LastError();
   812 
   813 		iBase = MapViewOfFile(iMapping, FILE_MAP_READ, 0, 0, 0);
   814 
   815 		if (!iBase)
   816 			{
   817 			CloseHandle(iMapping);
   818 			iMapping = 0;
   819 			return LastError();
   820 			}
   821 		}
   822 
   823 	if (!NtHeader())
   824 		{
   825 		Close();
   826 		return KErrNotSupported;
   827 		}
   828 	return KErrNone;
   829 	}
   830 
   831 EXPORT_C void Emulator::RImageFile::Close()
   832 	{
   833 	if (iMapping)
   834 		{
   835 		UnmapViewOfFile(iBase);
   836 		CloseHandle(iMapping);
   837 		iMapping = 0;
   838 		}
   839 	iBase = 0;
   840 	iModule = 0;
   841 	}