author | Slion |
Wed, 03 Feb 2010 22:15:32 +0100 | |
branch | anywhere |
changeset 50 | 999bb78c71ac |
parent 41 | d32f34975bbf |
permissions | -rw-r--r-- |
0 | 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> |
|
33
0173bcd7697c
Revision: 201001
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
22 |
#include <e32ldr_private.h> |
0 | 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); |
|
19
f6d3d9676ee4
Trying to figure out how to implement my WINC like compatibility layer. Going the emulation way is probably not so smart. We should not use the kernel but rather hook native functions in the Exec calls.
Slion
parents:
0
diff
changeset
|
787 |
char *pName = (char *)strrchr(LPCSTR(nameBuf), '\\'); |
0 | 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 |
} |