1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kernel/eka/euser/epoc/win32/emulator.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,841 @@
1.4 +// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +//
1.18 +
1.19 +#define _CRTIMP // we want to use the static runtime library
1.20 +#include <e32cmn.h>
1.21 +#include <e32cmn_private.h>
1.22 +#include <string.h>
1.23 +#include <emulator.h>
1.24 +#include <e32ldr.h>
1.25 +#include <e32ldr_private.h>
1.26 +#include <e32uid.h>
1.27 +
1.28 +#pragma data_seg(".data2")
1.29 +#ifdef __VC32__
1.30 +#pragma bss_seg(".data2")
1.31 +#endif
1.32 +static TBool UnicodeHost;
1.33 +static Emulator::SInit Data;
1.34 +#pragma data_seg()
1.35 +#ifdef __VC32__
1.36 +#pragma bss_seg()
1.37 +#endif
1.38 +
1.39 +/**
1.40 +Initializes a module and prepares it to handle requests.
1.41 +
1.42 +@param aInit An object of the structure SInit.
1.43 +
1.44 +@see SInit.
1.45 +*/
1.46 +EXPORT_C void Emulator::Init(const Emulator::SInit& aInit)
1.47 + {
1.48 + UnicodeHost = (GetVersion() & 0x80000000) ? FALSE : TRUE;
1.49 + Data = aInit;
1.50 + if (Data.iCodePage == 0)
1.51 + Data.iCodePage = CP_ACP;
1.52 + }
1.53 +
1.54 +LOCAL_C DWORD UStringLength(LPCSTR lpMultiByteStr)
1.55 +//
1.56 +// returns length of unicode string generated - assumes null terminated string
1.57 +//
1.58 + {
1.59 + return MultiByteToWideChar(Data.iCodePage,0,lpMultiByteStr,-1,0,0);
1.60 + }
1.61 +
1.62 +
1.63 +LOCAL_C DWORD ConvertToUnicode(LPCSTR aNarrow,LPWSTR aUnicode,DWORD aLength,BOOL aCharsRequired)
1.64 +//
1.65 +// Converts narrow string to unicode string
1.66 +//
1.67 + {
1.68 + DWORD uniLength=UStringLength(aNarrow);
1.69 + if(uniLength>aLength || uniLength==0)
1.70 + return aCharsRequired ? uniLength : 0;
1.71 + uniLength=MultiByteToWideChar(Data.iCodePage,0,aNarrow,-1,aUnicode,aLength);
1.72 + // return number of characters excluding the null terminator
1.73 + return uniLength ? uniLength-1 : 0;
1.74 + }
1.75 +
1.76 +
1.77 +LOCAL_C DWORD ConvertToNarrow(LPCWSTR aUnicode,LPSTR aNarrow,DWORD aLength)
1.78 +//
1.79 +// Converts unicode string to narrow string
1.80 +//
1.81 + {
1.82 + return WideCharToMultiByte(Data.iCodePage,0,aUnicode,-1,aNarrow,aLength,"@",NULL);
1.83 + }
1.84 +
1.85 +template <TUint S>
1.86 +struct Buf8
1.87 + {
1.88 +public:
1.89 + Buf8(LPCWSTR aUnicode);
1.90 + inline operator LPCSTR() const
1.91 + {return iPtr;}
1.92 +private:
1.93 + const char* iPtr;
1.94 + char iBuf[S];
1.95 + };
1.96 +
1.97 +template <TUint S>
1.98 +Buf8<S>::Buf8(LPCWSTR aUnicode)
1.99 + {
1.100 + if (aUnicode)
1.101 + {
1.102 + iPtr = iBuf;
1.103 + ConvertToNarrow(aUnicode,iBuf,S);
1.104 + }
1.105 + else
1.106 + {
1.107 + iPtr = NULL;
1.108 + }
1.109 + }
1.110 +
1.111 +
1.112 +
1.113 +/**
1.114 +Acquires the global lock for host interaction.
1.115 +*/
1.116 +EXPORT_C void Emulator::Lock()
1.117 + {
1.118 + Data.iLock();
1.119 + }
1.120 +
1.121 +/**
1.122 +Releases the global lock for host interaction.
1.123 +This may overwrite the error code for this thread and that is not the behaviour expected,
1.124 +so save and restore it.
1.125 +*/
1.126 +EXPORT_C void Emulator::Unlock()
1.127 + {
1.128 + DWORD error=GetLastError();
1.129 + Data.iUnlock();
1.130 + SetLastError(error);
1.131 + }
1.132 +
1.133 +/**
1.134 +Takes the current thread out of the emulator scheduling model.
1.135 +*/
1.136 +EXPORT_C void Emulator::Escape()
1.137 + {
1.138 + Data.iEscape();
1.139 + }
1.140 +
1.141 +/**
1.142 +Returns the calling thread into the emulator scheduling model.
1.143 +This may overwrite the error code for this thread and that is not the behaviour expected,
1.144 +so save and restore it.
1.145 +*/
1.146 +EXPORT_C void Emulator::Reenter()
1.147 + {
1.148 + DWORD error=GetLastError();
1.149 + Data.iReenter();
1.150 + SetLastError(error);
1.151 + }
1.152 +
1.153 +
1.154 +/**
1.155 +Jumps to the NThread Win32 SEH exception handler.
1.156 +
1.157 +@param aException Describes an exception.
1.158 +@param aContext Describes the context.
1.159 +
1.160 +@return A handler to handle the exception occurred
1.161 +*/
1.162 +EXPORT_C DWORD Emulator::Win32SEHException(EXCEPTION_RECORD* aException, CONTEXT* aContext)
1.163 + {
1.164 + return Data.iException(aException, aContext);
1.165 + }
1.166 +
1.167 +
1.168 +/**
1.169 +This function wraps the Win32 CreateDirectory API (see http://msdn2.microsoft.com/en-us/library/aa363855.aspx).
1.170 +*/
1.171 +EXPORT_C BOOL Emulator::CreateDirectory(LPCWSTR lpPathName,LPSECURITY_ATTRIBUTES lpSecurityAttributes)
1.172 + {
1.173 + __LOCK_HOST;
1.174 +
1.175 + if (UnicodeHost)
1.176 + return ::CreateDirectoryW(lpPathName, lpSecurityAttributes);
1.177 +
1.178 + return ::CreateDirectoryA(Buf8<MAX_PATH>(lpPathName),lpSecurityAttributes);
1.179 + }
1.180 +
1.181 +#ifdef __VC32__
1.182 +//disable unreachable code warning in VC++
1.183 +#pragma warning (disable : 4702)
1.184 +#endif
1.185 +
1.186 +
1.187 +/**
1.188 +Recursively ensures that the full directory exists.
1.189 +
1.190 +@param aPathName Provides the path name.
1.191 +
1.192 +@return TRUE, if the function succeeds
1.193 + FALSE, if the function fails
1.194 +*/
1.195 +EXPORT_C BOOL Emulator::CreateAllDirectories(LPCSTR aPathName)
1.196 + {
1.197 + __LOCK_HOST;
1.198 +
1.199 + char path[MAX_PATH];
1.200 + strcpy(path, aPathName);
1.201 + char* p = path;
1.202 + for (;;)
1.203 + {
1.204 + p = strchr(p, '\\');
1.205 + char temp=0;
1.206 + if (p)
1.207 + {
1.208 + temp = *++p;
1.209 + *p = '\0';
1.210 + }
1.211 + DWORD att = ::GetFileAttributesA(path);
1.212 + if ((att == -1 || !(att&FILE_ATTRIBUTE_DIRECTORY)) && !::CreateDirectoryA(path, NULL))
1.213 + return EFalse;
1.214 + if (!p)
1.215 + return ETrue;
1.216 + *p = temp;
1.217 + }
1.218 + }
1.219 +#ifdef __VC32__
1.220 +//enable unreachable code warning in VC++
1.221 +#pragma warning (default : 4702)
1.222 +#endif
1.223 +
1.224 +#ifndef INVALID_FILE_ATTRIBUTES
1.225 +#define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
1.226 +#endif
1.227 +
1.228 +
1.229 +/**
1.230 +This function wraps the Win32 CreateFile API (see http://msdn2.microsoft.com/en-us/library/aa363858.aspx).
1.231 +It also modifies file attributes depending on whether the file is hidden or not.
1.232 +*/
1.233 +EXPORT_C HANDLE Emulator::CreateFile(LPCWSTR lpFileName,DWORD dwDesiredAccess,DWORD dwShareMode,
1.234 + LPSECURITY_ATTRIBUTES lpSecurityAttributes,DWORD dwCreationDistribution,
1.235 + DWORD dwFlagsAndAttributes,HANDLE hTemplateFile)
1.236 + {
1.237 + __LOCK_HOST;
1.238 + HANDLE h;
1.239 + BOOL hidden = 0;
1.240 + DWORD att = INVALID_FILE_ATTRIBUTES;
1.241 + if(dwCreationDistribution==CREATE_ALWAYS)
1.242 + {
1.243 + att = ::GetFileAttributes(lpFileName);
1.244 + if(att!=INVALID_FILE_ATTRIBUTES && (att&FILE_ATTRIBUTE_HIDDEN))
1.245 + {
1.246 + hidden = ::SetFileAttributes(lpFileName, (att&~FILE_ATTRIBUTE_HIDDEN));
1.247 + }
1.248 + }
1.249 +
1.250 + if (UnicodeHost)
1.251 + h = ::CreateFileW(lpFileName,dwDesiredAccess,dwShareMode,lpSecurityAttributes,dwCreationDistribution,
1.252 + dwFlagsAndAttributes,hTemplateFile);
1.253 + else
1.254 + h = ::CreateFileA(Buf8<MAX_PATH>(lpFileName),dwDesiredAccess,dwShareMode,lpSecurityAttributes,dwCreationDistribution,
1.255 + dwFlagsAndAttributes,hTemplateFile);
1.256 +
1.257 + if(hidden && h!=INVALID_HANDLE_VALUE)
1.258 + {
1.259 + ::SetFileAttributes(lpFileName, att);
1.260 + }
1.261 + return h;
1.262 + }
1.263 +
1.264 +
1.265 +/**
1.266 +This function wraps the Win32 DeleteFile API (see http://msdn2.microsoft.com/en-us/library/aa363915.aspx).
1.267 +*/
1.268 +EXPORT_C BOOL Emulator::DeleteFile(LPCWSTR lpFileName)
1.269 + {
1.270 + __LOCK_HOST;
1.271 +
1.272 + if (UnicodeHost)
1.273 + return ::DeleteFileW(lpFileName);
1.274 +
1.275 + return ::DeleteFileA(Buf8<MAX_PATH>(lpFileName));
1.276 + }
1.277 +
1.278 +LOCAL_C TBool MapFindFileData(LPWIN32_FIND_DATAW lpFindFileData, LPWIN32_FIND_DATAA lpFindNarrow)
1.279 + {
1.280 + lpFindFileData->dwFileAttributes=lpFindNarrow->dwFileAttributes;
1.281 + lpFindFileData->ftCreationTime=lpFindNarrow->ftCreationTime;
1.282 + lpFindFileData->ftLastAccessTime=lpFindNarrow->ftLastAccessTime;
1.283 + lpFindFileData->ftLastWriteTime=lpFindNarrow->ftLastWriteTime;
1.284 + lpFindFileData->nFileSizeHigh=lpFindNarrow->nFileSizeHigh;
1.285 + lpFindFileData->nFileSizeLow=lpFindNarrow->nFileSizeLow;
1.286 +
1.287 + if(!MultiByteToWideChar(Data.iCodePage,0,lpFindNarrow->cFileName,-1,lpFindFileData->cFileName,MAX_PATH))
1.288 + return FALSE;
1.289 +
1.290 + if(lpFindNarrow->cAlternateFileName!=NULL)
1.291 + {
1.292 + // magic number 14 comes from MS documentation
1.293 + if(!MultiByteToWideChar(Data.iCodePage,0,lpFindNarrow->cAlternateFileName,-1,lpFindFileData->cAlternateFileName,14))
1.294 + return FALSE;
1.295 + }
1.296 + return TRUE;
1.297 + }
1.298 +
1.299 +
1.300 +/**
1.301 +This function wraps the Win32 FindFirstFile API (see http://msdn2.microsoft.com/en-us/library/aa364418.aspx).
1.302 +*/
1.303 +EXPORT_C HANDLE Emulator::FindFirstFile(LPCWSTR lpFileName,LPWIN32_FIND_DATAW lpFindFileData)
1.304 + {
1.305 + __LOCK_HOST;
1.306 +
1.307 + if (UnicodeHost)
1.308 + return ::FindFirstFileW(lpFileName, lpFindFileData);
1.309 +
1.310 + WIN32_FIND_DATAA lpFindNarrow;
1.311 + HANDLE h=::FindFirstFileA(Buf8<MAX_PATH>(lpFileName),&lpFindNarrow);
1.312 + if(h==INVALID_HANDLE_VALUE)
1.313 + return h;
1.314 +
1.315 + if (!MapFindFileData(lpFindFileData, &lpFindNarrow))
1.316 + {
1.317 + FindClose(h);
1.318 + return INVALID_HANDLE_VALUE;
1.319 + }
1.320 +
1.321 + return h;
1.322 + }
1.323 +
1.324 +
1.325 +/**
1.326 +This function wraps the Win32 FindNextFile API (see http://msdn2.microsoft.com/en-us/library/aa364428.aspx).
1.327 +*/
1.328 +EXPORT_C BOOL Emulator::FindNextFile(HANDLE hFindFile,LPWIN32_FIND_DATAW lpFindFileData)
1.329 + {
1.330 + __LOCK_HOST;
1.331 +
1.332 + if (UnicodeHost)
1.333 + return ::FindNextFileW(hFindFile, lpFindFileData);
1.334 +
1.335 + WIN32_FIND_DATAA lpFindNarrow;
1.336 + if(!::FindNextFileA(hFindFile,&lpFindNarrow))
1.337 + return FALSE;
1.338 +
1.339 + return MapFindFileData(lpFindFileData, &lpFindNarrow);
1.340 + }
1.341 +
1.342 +/**
1.343 +This function wraps the Win32 GetDiskFreeSpace API (see http://msdn2.microsoft.com/en-us/library/aa364935.aspx).
1.344 +*/
1.345 +EXPORT_C BOOL Emulator::GetDiskFreeSpace(LPCWSTR lpRootPathName,LPDWORD lpSectorsPerCluster,\
1.346 + LPDWORD lpBytesPerSector,LPDWORD lpNumberOfFreeClusters,\
1.347 + LPDWORD lpTotalNumberOfClusters)
1.348 + {
1.349 + __LOCK_HOST;
1.350 +
1.351 + if (UnicodeHost)
1.352 + return ::GetDiskFreeSpaceW(lpRootPathName,lpSectorsPerCluster,lpBytesPerSector,lpNumberOfFreeClusters,lpTotalNumberOfClusters);
1.353 +
1.354 + return ::GetDiskFreeSpaceA(Buf8<MAX_PATH>(lpRootPathName),lpSectorsPerCluster,lpBytesPerSector,lpNumberOfFreeClusters,lpTotalNumberOfClusters);
1.355 +
1.356 + }
1.357 +
1.358 +
1.359 +/**
1.360 +This function wraps the Win32 GetFileAttributes API (see http://msdn2.microsoft.com/en-us/library/aa364944.aspx).
1.361 +*/
1.362 +EXPORT_C DWORD Emulator::GetFileAttributes(LPCWSTR lpFileName)
1.363 + {
1.364 + __LOCK_HOST;
1.365 +
1.366 + if (UnicodeHost)
1.367 + return ::GetFileAttributesW(lpFileName);
1.368 +
1.369 + return ::GetFileAttributesA(Buf8<MAX_PATH>(lpFileName));
1.370 + }
1.371 +
1.372 +
1.373 +/**
1.374 +This function wraps the Win32 GetModuleHandle API (see http://msdn2.microsoft.com/en-us/library/ms683199.aspx).
1.375 +*/
1.376 +EXPORT_C HMODULE Emulator::GetModuleHandle(LPCWSTR lpModuleName)
1.377 + {
1.378 + __LOCK_HOST;
1.379 +
1.380 + if (UnicodeHost)
1.381 + return ::GetModuleHandleW(lpModuleName);
1.382 +
1.383 + return ::GetModuleHandleA(Buf8<MAX_PATH>(lpModuleName));
1.384 + }
1.385 +
1.386 +
1.387 +/**
1.388 +This function wraps the Win32 GetModuleFileName API (see http://msdn2.microsoft.com/en-us/library/ms683197.aspx).
1.389 +*/
1.390 +EXPORT_C DWORD Emulator::GetModuleFileName(HMODULE hModule, LPWSTR lpFilename)
1.391 + {
1.392 + __LOCK_HOST;
1.393 + if (UnicodeHost)
1.394 + return ::GetModuleFileNameW(hModule, lpFilename, MAX_PATH);
1.395 + char fn[MAX_PATH];
1.396 + DWORD r=::GetModuleFileNameA(hModule, fn, MAX_PATH);
1.397 + if (r>MAX_PATH||r==0)
1.398 + return 0;
1.399 + return ConvertToUnicode(fn, lpFilename, MAX_PATH, TRUE);
1.400 + }
1.401 +
1.402 +
1.403 +/**
1.404 +This function wraps the Win32 GetTempPath API (see http://msdn2.microsoft.com/en-us/library/Aa364992.aspx).
1.405 +*/
1.406 +EXPORT_C DWORD Emulator::GetTempPath(DWORD nBufferLength,LPWSTR lpBuff)
1.407 + {
1.408 + __LOCK_HOST;
1.409 +
1.410 + if (UnicodeHost)
1.411 + return ::GetTempPathW(nBufferLength,lpBuff);
1.412 +
1.413 + char path[MAX_PATH];
1.414 + DWORD r=::GetTempPathA(MAX_PATH,path);
1.415 + if(r>MAX_PATH||r==0)
1.416 + return 0;
1.417 + return ConvertToUnicode(path,lpBuff,nBufferLength,TRUE);
1.418 + }
1.419 +
1.420 +
1.421 +/**
1.422 +This function wraps the Win32 GetCurrentDirectory API (see http://msdn2.microsoft.com/en-us/library/aa364934.aspx).
1.423 +*/
1.424 +EXPORT_C DWORD Emulator::GetCurrentDirectory(DWORD nBufferLength,LPWSTR lpBuff)
1.425 + {
1.426 + __LOCK_HOST;
1.427 +
1.428 + if (UnicodeHost)
1.429 + return ::GetCurrentDirectoryW(nBufferLength,lpBuff);
1.430 +
1.431 + char path[MAX_PATH];
1.432 + DWORD r=::GetCurrentDirectoryA(MAX_PATH,path);
1.433 + if(r>MAX_PATH||r==0)
1.434 + return 0;
1.435 + return ConvertToUnicode(path,lpBuff,nBufferLength,TRUE);
1.436 + }
1.437 +
1.438 +
1.439 +/**
1.440 +This function wraps the Win32 GetVolumeInformation API (see http://msdn2.microsoft.com/en-us/library/aa364993.aspx).
1.441 +*/
1.442 +EXPORT_C BOOL Emulator::GetVolumeInformation(LPCWSTR lpRootPathName,LPWSTR lpVolumeNameBuffer,DWORD nVolumeNameSize,
1.443 + LPDWORD lpVolumeSerialNumber,LPDWORD lpMaximumComponentLength,
1.444 + LPDWORD lpFileSystemFlags,LPWSTR,DWORD)
1.445 + {
1.446 + __LOCK_HOST;
1.447 +
1.448 + // lpfileSystemNameBuffer always NULL so no need to convert
1.449 + if (UnicodeHost)
1.450 + return ::GetVolumeInformationW(lpRootPathName,lpVolumeNameBuffer,nVolumeNameSize,lpVolumeSerialNumber,
1.451 + lpMaximumComponentLength,lpFileSystemFlags,NULL,0);
1.452 +
1.453 + char volName[MAX_PATH];
1.454 + BOOL res=::GetVolumeInformationA(Buf8<MAX_PATH>(lpRootPathName),volName,MAX_PATH,lpVolumeSerialNumber,
1.455 + lpMaximumComponentLength,lpFileSystemFlags,NULL,0);
1.456 +
1.457 + if(res && lpVolumeNameBuffer)
1.458 + ConvertToUnicode(volName,lpVolumeNameBuffer,nVolumeNameSize,FALSE);
1.459 + return res;
1.460 + }
1.461 +
1.462 +
1.463 +/**
1.464 +This function wraps the Win32 LoadLibrary API (see http://msdn2.microsoft.com/en-us/library/ms684175.aspx).
1.465 +*/
1.466 +EXPORT_C HMODULE Emulator::LoadLibrary(LPCWSTR lpLibFileName)
1.467 + {
1.468 + __LOCK_HOST;
1.469 +
1.470 + if (UnicodeHost)
1.471 + return ::LoadLibraryW(lpLibFileName);
1.472 +
1.473 + return ::LoadLibraryA(Buf8<MAX_PATH>(lpLibFileName));
1.474 + }
1.475 +
1.476 +
1.477 +/**
1.478 +This function wraps the Win32 FreeLibrary API (see http://msdn2.microsoft.com/en-us/library/ms683152.aspx).
1.479 +*/
1.480 +EXPORT_C BOOL Emulator::FreeLibrary(HMODULE hLibModule)
1.481 + {
1.482 + __LOCK_HOST;
1.483 + return ::FreeLibrary(hLibModule);
1.484 + }
1.485 +
1.486 +
1.487 +
1.488 +/**
1.489 +This function wraps the Win32 MoveFile API (see http://msdn2.microsoft.com/en-us/library/aa365239.aspx).
1.490 +*/
1.491 +EXPORT_C BOOL Emulator::MoveFile(LPCWSTR lpExistingFileName,LPCWSTR lpNewFileName)
1.492 + {
1.493 + __LOCK_HOST;
1.494 +
1.495 + if (UnicodeHost)
1.496 + return ::MoveFileW(lpExistingFileName,lpNewFileName);
1.497 +
1.498 + return ::MoveFileA(Buf8<MAX_PATH>(lpExistingFileName),Buf8<MAX_PATH>(lpNewFileName));
1.499 + }
1.500 +
1.501 +
1.502 +/**
1.503 +This function wraps the Win32 CopyFile API (see http://msdn2.microsoft.com/en-us/library/aa363851.aspx).
1.504 +*/
1.505 +EXPORT_C BOOL Emulator::CopyFile(LPCWSTR lpExistingFileName,LPCWSTR lpNewFileName,BOOL aFailIfExists)
1.506 + {
1.507 + __LOCK_HOST;
1.508 +
1.509 + if (UnicodeHost)
1.510 + return ::CopyFileW(lpExistingFileName,lpNewFileName,aFailIfExists);
1.511 +
1.512 + return ::CopyFileA(Buf8<MAX_PATH>(lpExistingFileName),Buf8<MAX_PATH>(lpNewFileName),aFailIfExists);
1.513 + }
1.514 +
1.515 +
1.516 +/**
1.517 +This function wraps the Win32 OutputDebugString API (see http://msdn2.microsoft.com/en-us/library/aa363362.aspx).
1.518 +*/
1.519 +EXPORT_C VOID Emulator::OutputDebugString(LPCWSTR lpOutputString)
1.520 + {
1.521 + if (UnicodeHost)
1.522 + ::OutputDebugStringW(lpOutputString);
1.523 + else
1.524 + ::OutputDebugStringA(Buf8<1024>(lpOutputString));
1.525 + }
1.526 +
1.527 +
1.528 +
1.529 +/**
1.530 +This function wraps the Win32 RemoveDirectory API (see http://msdn2.microsoft.com/en-us/library/aa365488.aspx).
1.531 +*/
1.532 +EXPORT_C BOOL Emulator::RemoveDirectory(LPCWSTR lpPathName)
1.533 + {
1.534 + __LOCK_HOST;
1.535 +
1.536 + if (UnicodeHost)
1.537 + return ::RemoveDirectoryW(lpPathName);
1.538 +
1.539 + return ::RemoveDirectoryA(Buf8<MAX_PATH>(lpPathName));
1.540 + }
1.541 +
1.542 +
1.543 +/**
1.544 +This function wraps the Win32 SetFileAttributes API (see http://msdn2.microsoft.com/en-us/library/aa365535.aspx).
1.545 +*/
1.546 +
1.547 +EXPORT_C BOOL Emulator::SetFileAttributes(LPCWSTR lpFileName,DWORD dwFileAttributes)
1.548 + {
1.549 + __LOCK_HOST;
1.550 +
1.551 + if (UnicodeHost)
1.552 + return ::SetFileAttributesW(lpFileName,dwFileAttributes);
1.553 +
1.554 + return ::SetFileAttributesA(Buf8<MAX_PATH>(lpFileName),dwFileAttributes);
1.555 + }
1.556 +
1.557 +
1.558 +
1.559 +/**
1.560 +This function wraps the Win32 SetVolumeLabel API (see http://msdn2.microsoft.com/en-us/library/aa365560.aspx).
1.561 +*/
1.562 +EXPORT_C BOOL Emulator::SetVolumeLabel(LPCWSTR lpRootPathName,LPCWSTR lpVolumeName)
1.563 + {
1.564 + __LOCK_HOST;
1.565 +
1.566 + if (UnicodeHost)
1.567 + return ::SetVolumeLabelW(lpRootPathName,lpVolumeName);
1.568 +
1.569 + return ::SetVolumeLabelA(Buf8<MAX_PATH>(lpRootPathName),Buf8<MAX_PATH>(lpVolumeName));
1.570 + }
1.571 +
1.572 +
1.573 +/**
1.574 +Maps an NT error to an Epoc32 error.
1.575 +
1.576 +@return Last-error code of the calling thread.
1.577 +*/
1.578 +EXPORT_C TInt Emulator::LastError()
1.579 +
1.580 +// For other error codes look at MSDN "Numerical List of Error Codes"
1.581 + {
1.582 + switch (GetLastError())
1.583 + {
1.584 + case ERROR_SUCCESS: return KErrNone;
1.585 + case ERROR_INVALID_DRIVE: return KErrNotReady;
1.586 + case ERROR_INVALID_NAME:
1.587 + case ERROR_FILENAME_EXCED_RANGE:
1.588 + case ERROR_OPEN_FAILED: return KErrBadName;
1.589 + case ERROR_INVALID_HANDLE: return KErrBadHandle;
1.590 + case ERROR_NOT_SUPPORTED:
1.591 + case ERROR_INVALID_FUNCTION: return KErrNotSupported;
1.592 + case ERROR_SHARING_VIOLATION:
1.593 + case ERROR_ACCESS_DENIED:
1.594 + case ERROR_WRITE_PROTECT: return KErrAccessDenied;
1.595 + case ERROR_LOCK_VIOLATION: return KErrLocked;
1.596 + case ERROR_FILE_NOT_FOUND:
1.597 + case ERROR_MOD_NOT_FOUND: return KErrNotFound;
1.598 + case ERROR_DIRECTORY:
1.599 + case ERROR_BAD_PATHNAME:
1.600 + case ERROR_PATH_NOT_FOUND: return KErrPathNotFound;
1.601 + case ERROR_ALREADY_EXISTS:
1.602 + case ERROR_FILE_EXISTS: return KErrAlreadyExists;
1.603 + case ERROR_NOT_READY: return KErrNotReady;
1.604 + case ERROR_UNRECOGNIZED_VOLUME:
1.605 + case ERROR_NOT_DOS_DISK: return KErrUnknown;
1.606 + case ERROR_UNRECOGNIZED_MEDIA:
1.607 + case ERROR_BAD_EXE_FORMAT: return KErrCorrupt;
1.608 + case ERROR_NO_MORE_FILES: return KErrEof;
1.609 + case ERROR_DIR_NOT_EMPTY: return KErrInUse;
1.610 + case ERROR_INVALID_USER_BUFFER:
1.611 + case ERROR_NOT_ENOUGH_MEMORY:
1.612 + case ERROR_INSUFFICIENT_BUFFER:
1.613 + case ERROR_OUTOFMEMORY: return KErrNoMemory;
1.614 + case ERROR_DISK_FULL: return KErrDiskFull;
1.615 + case ERROR_INVALID_DATA:
1.616 + case ERROR_INVALID_PARAMETER: return KErrArgument;
1.617 + case ERROR_OPERATION_ABORTED: return KErrCancel;
1.618 +
1.619 + default: return KErrGeneral;
1.620 + }
1.621 + }
1.622 +
1.623 +/**
1.624 +This function wraps the Win32 GetProcAddress API (see http://msdn2.microsoft.com/en-us/library/ms683212.aspx).
1.625 +*/
1.626 +FARPROC Emulator::GetProcAddress(HMODULE hModule, LPCSTR lpProcName)
1.627 + {
1.628 + __LOCK_HOST;
1.629 + return ::GetProcAddress(hModule, lpProcName);
1.630 + }
1.631 +
1.632 +
1.633 +
1.634 +// image file support
1.635 +
1.636 +// loaded modules
1.637 +
1.638 +
1.639 +/**
1.640 +Gets the header format of the file system.
1.641 +
1.642 +@return Returns the header format of the file system.
1.643 +*/
1.644 +EXPORT_C const IMAGE_NT_HEADERS32* Emulator::TModule::NtHeader() const
1.645 + {
1.646 + if (!IsValid())
1.647 + return 0;
1.648 + const IMAGE_DOS_HEADER* dhead = (const IMAGE_DOS_HEADER*)Translate(0);
1.649 + if ( IMAGE_DOS_SIGNATURE != dhead->e_magic )
1.650 + return 0;
1.651 + if (dhead->e_lfarlc < sizeof(IMAGE_DOS_HEADER))
1.652 + return 0;
1.653 + const IMAGE_NT_HEADERS32* ntHead = (const IMAGE_NT_HEADERS32*)Translate(dhead->e_lfanew);
1.654 + if ( ntHead->Signature != IMAGE_NT_SIGNATURE )
1.655 + return 0;
1.656 + return ntHead;
1.657 + }
1.658 +
1.659 +
1.660 +/**
1.661 +Constructor which sets the handles of loaded module to the specified module.
1.662 +
1.663 +@param aModuleName Holds the name of the module to be loaded.
1.664 +*/
1.665 +EXPORT_C Emulator::TModule::TModule(LPCSTR aModuleName)
1.666 + : iModule(GetModuleHandleA(aModuleName)), iBase(iModule)
1.667 + {
1.668 + if (!NtHeader())
1.669 + {
1.670 + iModule = 0;
1.671 + iBase = 0;
1.672 + }
1.673 + }
1.674 +
1.675 +
1.676 +/**
1.677 +Gets the pointer of the section header if the header name matches with the buffer aSection[].
1.678 +
1.679 +@param aSection[] A buffer of type BYTE.
1.680 +
1.681 +@return Returns the pointer to section header of the file system.
1.682 +*/
1.683 +EXPORT_C const IMAGE_SECTION_HEADER* Emulator::TModule::SectionHeader(const BYTE aSection[]) const
1.684 + {
1.685 + const IMAGE_NT_HEADERS32* ntHead = NtHeader();
1.686 + if (!ntHead)
1.687 + return 0;
1.688 +
1.689 + const IMAGE_SECTION_HEADER* imgHead = (const IMAGE_SECTION_HEADER*)((TUint8*)&ntHead->OptionalHeader + ntHead->FileHeader.SizeOfOptionalHeader);
1.690 + const IMAGE_SECTION_HEADER* end = imgHead + ntHead->FileHeader.NumberOfSections;
1.691 + for (; imgHead < end; ++imgHead)
1.692 + {
1.693 + if (memcmp(imgHead->Name, aSection, IMAGE_SIZEOF_SHORT_NAME)==0)
1.694 + return imgHead;
1.695 + }
1.696 + return 0;
1.697 + }
1.698 +
1.699 +
1.700 +/**
1.701 +Points to the first byte or first page of the loaded module or mapped file image.
1.702 +
1.703 +@param aSection[] A buffer of type BYTE.
1.704 +
1.705 +@return TAny Returns first byte of the loaded module or first page of the mapped file image.
1.706 +*/
1.707 +EXPORT_C const TAny* Emulator::TModule::Section(const BYTE aSection[]) const
1.708 + {
1.709 + const IMAGE_SECTION_HEADER* imgHead = SectionHeader(aSection);
1.710 + if (imgHead)
1.711 + return Translate(IsLoaded() ? imgHead->VirtualAddress : imgHead->PointerToRawData);
1.712 + return 0;
1.713 + }
1.714 +
1.715 +
1.716 +/**
1.717 +Go through the section headers looking for UID section.
1.718 +
1.719 +@param aType Contains a UID type.
1.720 +*/
1.721 +EXPORT_C void Emulator::TModule::GetUids(TUidType& aType) const
1.722 + {
1.723 + const TEmulatorImageHeader* hdr = (const TEmulatorImageHeader*)Section(KWin32SectionName_Symbian);
1.724 + if (hdr)
1.725 + aType = *(const TUidType*)&hdr->iUids[0];
1.726 + }
1.727 +
1.728 +
1.729 +/**
1.730 +Goes through section headers and gets the information of file system.
1.731 +
1.732 +@param aInfo Contains the information of the file system.
1.733 +*/
1.734 +EXPORT_C void Emulator::TModule::GetInfo(TProcessCreateInfo& aInfo) const
1.735 + {
1.736 + aInfo.iExceptionDescriptor = 0;
1.737 + const IMAGE_NT_HEADERS32* ntHead = NtHeader();
1.738 + if (ntHead)
1.739 + {
1.740 + const TEmulatorImageHeader* hdr = (const TEmulatorImageHeader*)Section(KWin32SectionName_Symbian);
1.741 + if (hdr)
1.742 + {
1.743 + aInfo.iUids = *(const TUidType*)&hdr->iUids[0];
1.744 + TBool isExe = (hdr->iUids[0].iUid==KExecutableImageUidValue);
1.745 + TBool data_section_present = (Section(KWin32SectionName_EpocData)!=NULL);
1.746 + TBool data = hdr->iFlags & KEmulatorImageFlagAllowDllData;
1.747 + if (data_section_present && isExe)
1.748 + data = ETrue;
1.749 + aInfo.iBssSize=data?1:0;
1.750 + aInfo.iDataSize=0;
1.751 + aInfo.iTotalDataSize=aInfo.iBssSize;
1.752 + aInfo.iDepCount = 0;
1.753 + aInfo.iHeapSizeMin = ntHead->OptionalHeader.SizeOfHeapCommit;
1.754 + aInfo.iHeapSizeMax = ntHead->OptionalHeader.SizeOfHeapReserve;
1.755 + aInfo.iStackSize = 0x1000;
1.756 + aInfo.iPriority = hdr->iPriority;
1.757 + aInfo.iHandle = NULL;
1.758 + aInfo.iS = hdr->iS;
1.759 + aInfo.iModuleVersion = hdr->iModuleVersion;
1.760 + if (ntHead->FileHeader.Characteristics & IMAGE_FILE_DLL)
1.761 + aInfo.iAttr |= ECodeSegAttHDll;
1.762 + }
1.763 + }
1.764 + GetUids(aInfo.iUids);
1.765 + }
1.766 +
1.767 +
1.768 +/**
1.769 +Finds the import section from the data directory. This relies on the module being loaded.
1.770 +
1.771 +@return Returns the imported executable.
1.772 +*/
1.773 +EXPORT_C const IMAGE_IMPORT_DESCRIPTOR* Emulator::TModule::Imports() const
1.774 + {
1.775 + if (!IsLoaded())
1.776 + return NULL;
1.777 + const IMAGE_NT_HEADERS32* ntHead = NtHeader();
1.778 + if (!ntHead)
1.779 + return NULL;
1.780 + DWORD va = ntHead->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
1.781 + if (!va)
1.782 + return NULL;
1.783 + return (const IMAGE_IMPORT_DESCRIPTOR*)Translate(va);
1.784 + }
1.785 +
1.786 +// modules in the file system
1.787 +EXPORT_C TInt Emulator::RImageFile::Open(LPCTSTR aImageFile)
1.788 + {
1.789 + Buf8<MAX_PATH> nameBuf(aImageFile);
1.790 + char *pName = (char *)strrchr(LPCSTR(nameBuf), '\\');
1.791 + pName ? ++pName : pName = (char *)LPCSTR(nameBuf);
1.792 +
1.793 + __LOCK_HOST;
1.794 + iMapping = OpenFileMapping(FILE_MAP_READ, FALSE, (LPCTSTR)pName);
1.795 + if (!iMapping)
1.796 + {
1.797 + if (pName == (char *)LPCSTR(nameBuf))
1.798 + iModule = Emulator::GetModuleHandle(aImageFile);
1.799 + if (iModule)
1.800 + iBase = iModule;
1.801 + else
1.802 + {
1.803 + // need to map the file instead
1.804 + HANDLE file = Emulator::CreateFile(aImageFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
1.805 + if (file == INVALID_HANDLE_VALUE)
1.806 + return LastError();
1.807 + iMapping = CreateFileMappingA(file, NULL, PAGE_READONLY, 0, 0, pName);
1.808 + CloseHandle(file);
1.809 + }
1.810 + }
1.811 + if (!iModule)
1.812 + {
1.813 + if (!iMapping)
1.814 + return LastError();
1.815 +
1.816 + iBase = MapViewOfFile(iMapping, FILE_MAP_READ, 0, 0, 0);
1.817 +
1.818 + if (!iBase)
1.819 + {
1.820 + CloseHandle(iMapping);
1.821 + iMapping = 0;
1.822 + return LastError();
1.823 + }
1.824 + }
1.825 +
1.826 + if (!NtHeader())
1.827 + {
1.828 + Close();
1.829 + return KErrNotSupported;
1.830 + }
1.831 + return KErrNone;
1.832 + }
1.833 +
1.834 +EXPORT_C void Emulator::RImageFile::Close()
1.835 + {
1.836 + if (iMapping)
1.837 + {
1.838 + UnmapViewOfFile(iBase);
1.839 + CloseHandle(iMapping);
1.840 + iMapping = 0;
1.841 + }
1.842 + iBase = 0;
1.843 + iModule = 0;
1.844 + }