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