source: trunk/src/kernel32/hmfile.cpp@ 22018

Last change on this file since 22018 was 21667, checked in by dmik, 14 years ago

kernel32: Fixed a regression in r21655 that caused crashes in DOSCALL1 when writing to memory mapped files. The wrong code path would incorrectly invalidate memory pages on each write. Closes Java ticket 129.

File size: 50.3 KB
Line 
1/* $Id: hmfile.cpp,v 1.46 2004-04-02 15:14:54 sandervl Exp $ */
2
3/*
4 * File IO win32 apis
5 *
6 * Copyright 1999-2000 Sander van Leeuwen
7 *
8 *
9 * Project Odin Software License can be found in LICENSE.TXT
10 *
11 */
12
13/*****************************************************************************
14 * Remark *
15 *****************************************************************************
16 */
17
18//#define DEBUG_LOCAL
19
20#ifdef DEBUG_LOCAL
21# define dprintfl(a) dprintf(a)
22#else
23inline void ignore_dprintf(...){}
24# define dprintfl(a) ignore_dprintf(a)
25#endif
26
27/*****************************************************************************
28 * Includes *
29 *****************************************************************************/
30
31#include <os2win.h>
32#include <string.h>
33#include "HandleManager.h"
34#include "HMFile.h"
35#include "mmap.h"
36#include "oslibdos.h"
37#include <customloader.h>
38
39#define DBG_LOCALLOG DBG_hmfile
40#include "dbglocal.h"
41
42static void ParsePath(LPCSTR lpszFileName, LPSTR lpszParsedFileName, DWORD length);
43
44
45class HMFileInfo
46{
47public:
48 HMFileInfo(HANDLE hFile, LPSTR lpszFileName, PVOID lpSecurityAttributes);
49 ~HMFileInfo();
50
51 char *lpszFileName;
52 PVOID lpSecurityAttributes;
53 DWORD dwLXOffset;
54};
55
56
57/*****************************************************************************
58 * Name : DWORD HMDeviceFileClass::CreateFile
59 * Purpose : this is called from the handle manager if a CreateFile() is
60 * performed on a handle
61 * Parameters: LPCSTR lpFileName name of the file / device
62 * PHMHANDLEDATA pHMHandleData data of the NEW handle
63 * PVOID lpSecurityAttributes ignored
64 * PHMHANDLEDATA pHMHandleDataTemplate data of the template handle
65 * Variables :
66 * Result :
67 * Remark :
68 * Status : NO_ERROR - API succeeded
69 * other - what is to be set in SetLastError
70 *
71 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
72 *****************************************************************************/
73
74DWORD HMDeviceFileClass::CreateFile (LPCSTR lpFileName,
75 PHMHANDLEDATA pHMHandleData,
76 PVOID lpSecurityAttributes,
77 PHMHANDLEDATA pHMHandleDataTemplate)
78{
79 HFILE hFile;
80 HFILE hTemplate;
81 char filepath[260];
82
83 dprintfl(("KERNEL32: HMDeviceFileClass::CreateFile %s(%s,%08x,%08x,%08x)\n",
84 lpHMDeviceName,
85 lpFileName,
86 pHMHandleData,
87 lpSecurityAttributes,
88 pHMHandleDataTemplate));
89
90 ParsePath(lpFileName, filepath, sizeof(filepath));
91
92 //convert to long file name if in 8.3 hashed format
93 GetLongPathNameA(filepath, filepath, sizeof(filepath));
94 lpFileName = filepath;
95
96 // create from template
97 if (pHMHandleDataTemplate != NULL)
98 hTemplate = pHMHandleDataTemplate->hHMHandle;
99 else
100 hTemplate = 0;
101
102 //TODO: FILE_SHARE_DELETE
103 hFile = OSLibDosCreateFile((LPSTR)lpFileName,
104 pHMHandleData->dwAccess,
105 pHMHandleData->dwShare,
106 (LPSECURITY_ATTRIBUTES)lpSecurityAttributes,
107 pHMHandleData->dwCreation,
108 pHMHandleData->dwFlags,
109 hTemplate);
110
111 if (hFile != INVALID_HANDLE_ERROR)
112 {
113 pHMHandleData->dwUserData = (DWORD) new HMFileInfo(hFile, (LPSTR)lpFileName, lpSecurityAttributes);
114 pHMHandleData->hHMHandle = hFile;
115 return (NO_ERROR);
116 }
117 else {
118 dprintf(("CreateFile failed; error %d", GetLastError()));
119 return(GetLastError());
120 }
121}
122
123/*****************************************************************************
124 * Name : DWORD HMDeviceFileClass::OpenFile
125 * Purpose : this is called from the handle manager if a OpenFile() is
126 * performed on a handle
127 * Parameters: LPCSTR lpFileName name of the file / device
128 * PHMHANDLEDATA pHMHandleData data of the NEW handle
129 * PVOID lpSecurityAttributes ignored
130 * PHMHANDLEDATA pHMHandleDataTemplate data of the template handle
131 * Variables :
132 * Result :
133 * Remark : TODO: Check if this implementation is complete and 100% correct
134 * UTC Time or Localtime ?
135 * GetFileTime is changed, Returns UTC-time yet !!!!!
136 * Status : NO_ERROR - API succeeded
137 * other - what is to be set in SetLastError
138 *
139 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
140 *****************************************************************************/
141
142DWORD HMDeviceFileClass::OpenFile (LPCSTR lpszFileName,
143 PHMHANDLEDATA pHMHandleData,
144 OFSTRUCT *pOFStruct,
145 UINT fuMode)
146{
147 HFILE hFile;
148 FILETIME filetime;
149 WORD filedatetime[2];
150 char filepath[260];
151 LPSTR lpFileName = (LPSTR)lpszFileName;
152
153 SetLastError(ERROR_SUCCESS);
154
155 //Re-open using name in OFSTRUCT
156 if(fuMode & OF_REOPEN)
157 lpFileName = (LPSTR)pOFStruct->szPathName;
158 else memset(pOFStruct, 0, sizeof(OFSTRUCT));
159
160 dprintf(("KERNEL32: HMDeviceFileClass::OpenFile %s(%s,%08x,%08x,%08x)", lpHMDeviceName,
161 lpFileName, pHMHandleData, pOFStruct, fuMode));
162
163 if(lpFileName == NULL) {
164 dprintf(("Invalid name (NULL)!"));
165 SetLastError(ERROR_INVALID_NAME);
166 return HFILE_ERROR;
167 }
168
169 if(!strchr(lpFileName, ':') && !strchr(lpFileName, '\\'))
170 {
171 //filename only; search for file in following order
172 //1: dir from which the app loaded
173 //2: current dir
174 //3: windows system dir
175 //4: windows dir
176 //5: dirs in path path environment variable
177 //SearchPath does exactly that
178 LPSTR filenameinpath;
179
180 if (SearchPathA(NULL, lpFileName, NULL, sizeof(filepath), filepath, &filenameinpath) == 0)
181 {
182 if (!(fuMode & (OF_CREATE | OF_PARSE)))
183 {
184 pOFStruct->nErrCode = ERROR_FILE_NOT_FOUND; /* What about initializing the struct? */
185 SetLastError(ERROR_FILE_NOT_FOUND);
186 return HFILE_ERROR;
187 }
188
189 /*
190 * OF_PARSE | OF_CREATE:
191 * Assume file in current directory.
192 */
193 GetCurrentDirectoryA(sizeof(filepath), filepath);
194 strcat(strcat(filepath, "\\"), lpFileName);
195 GetLongPathNameA(filepath, filepath, sizeof(filepath));
196 }
197 lpFileName = filepath;
198 }
199 else {
200 #if 1 /* Canonicalize the path should be the right thing to do I think... */
201 GetFullPathNameA(lpFileName, sizeof(filepath), filepath, NULL);
202 #else
203 ParsePath(lpFileName, filepath, sizeof(filepath));
204 #endif
205
206 //convert to long file name if in 8.3 hashed format
207 GetLongPathNameA(filepath, filepath, sizeof(filepath));
208 lpFileName = filepath;
209 }
210
211 // filling OFSTRUCT
212 pOFStruct->cBytes = sizeof(OFSTRUCT);
213 pOFStruct->nErrCode = 0;
214 strncpy((char *)pOFStruct->szPathName, lpFileName, OFS_MAXPATHNAME);
215 pOFStruct->szPathName[OFS_MAXPATHNAME-1] = 0;
216
217
218 /*
219 * Do the parse stuff now and do a quick exit.
220 * Based on testcase (5) and MSDN:
221 * "OF_PARSE Fills the OFSTRUCT structure but carries out no other action."
222 */
223 if (fuMode & OF_PARSE)
224 {
225 CHAR szDrive[4];
226 *(PULONG)&szDrive[0] = *(PULONG)&pOFStruct->szPathName[0];
227 szDrive[3] = '\0';
228 pOFStruct->fFixedDisk = (GetDriveTypeA(szDrive) != DRIVE_REMOVABLE);
229 SetLastError(NO_ERROR);
230 return NO_ERROR;
231 }
232
233
234 hFile = OSLibDosOpenFile((LPSTR)lpFileName, fuMode);
235
236 if(hFile != INVALID_HANDLE_ERROR)
237 {
238 //Needed for GetFileTime
239 pHMHandleData->hHMHandle = hFile;
240 GetFileTime(pHMHandleData,
241 NULL,
242 NULL,
243 &filetime );
244
245 /* UTC Time or Localtime ? GetFileTime Returns UTC-time yet ? !!!!! */
246 FileTimeToDosDateTime(&filetime,
247 &filedatetime[0],
248 &filedatetime[1] );
249 memcpy(pOFStruct->reserved, filedatetime, sizeof(pOFStruct->reserved));
250
251 if(fuMode & OF_DELETE)
252 {
253 OSLibDosClose(hFile);
254 OSLibDosDelete((LPSTR)lpFileName);
255 }
256 else
257 if(fuMode & OF_EXIST)
258 {
259 OSLibDosClose(hFile);
260 hFile = HFILE_ERROR;
261 }
262
263 if((fuMode & OF_VERIFY))
264 {//TODO: what's this?? we copy the time above...
265 if(memcmp(pOFStruct->reserved, filedatetime, sizeof(pOFStruct->reserved)))
266 {
267 OSLibDosClose(hFile);
268 SetLastError(ERROR_FILE_NOT_FOUND);
269 }
270 hFile = HFILE_ERROR;
271 }
272
273 pOFStruct->nErrCode = GetLastError();
274 pHMHandleData->hHMHandle = hFile;
275
276 if(hFile != HFILE_ERROR) {
277 pHMHandleData->dwUserData = (DWORD) new HMFileInfo(hFile, (LPSTR)lpFileName, NULL);
278 }
279 return (NO_ERROR);
280 }
281 else {
282 DWORD rc = GetLastError();
283
284 if(fuMode & OF_EXIST)
285 {
286 if(rc == ERROR_OPEN_FAILED) {
287 SetLastError(ERROR_FILE_NOT_FOUND);
288 }
289 }
290 //todo: OF_PROMPT handling (pop up message box)
291 }
292 // error branch
293 pOFStruct->nErrCode = GetLastError();
294 dprintf(("KERNEL32: HMDeviceFileClass::OpenFile Error %08xh\n",
295 pOFStruct->nErrCode));
296
297 // return != NO_ERROR => error code
298 return(hFile);
299}
300
301/*****************************************************************************
302 * Name : HMDeviceFileClass::DuplicateHandle
303 * Purpose :
304 * Parameters:
305 * various parameters as required
306 * Variables :
307 * Result :
308 * Remark : DUPLICATE_CLOSE_SOURCE flag handled in HMDuplicateHandle
309 *
310 * Status : partially implemented
311 *
312 * Author : SvL
313 *****************************************************************************/
314BOOL HMDeviceFileClass::DuplicateHandle(HANDLE srchandle, PHMHANDLEDATA pHMHandleData,
315 HANDLE srcprocess,
316 PHMHANDLEDATA pHMSrcHandle,
317 HANDLE destprocess,
318 DWORD fdwAccess,
319 BOOL fInherit,
320 DWORD fdwOptions,
321 DWORD fdwOdinOptions)
322{
323 HMFileInfo *srcfileinfo = (HMFileInfo *)pHMSrcHandle->dwUserData;
324 DWORD rc;
325
326 dprintf(("KERNEL32:HMDeviceFileClass::DuplicateHandle (%08x,%08x,%08x,%08x)",
327 pHMHandleData,
328 srcprocess,
329 pHMSrcHandle->hHMHandle,
330 destprocess));
331
332 //TODO: Inheritance of file handles won't work!
333
334 if(destprocess != srcprocess)
335 {
336 //TODO:!!!!
337 dprintf(("ERROR: DuplicateHandle; different processes not yet supported!!"));
338 return FALSE;
339 }
340
341 if(srcfileinfo)
342 {
343 //SvL: Special duplicatehandle option used by memory mapped class to duplicate
344 // file handle
345 // Can't use DosDupHandle or else there can be a sharing violation
346 // when an app tries to access the same file again
347 if(fdwOdinOptions)
348 {
349 HMHANDLEDATA duphdata;
350
351 memcpy(&duphdata, pHMHandleData, sizeof(duphdata));
352 duphdata.dwCreation = OPEN_EXISTING;
353
354 if(CreateFile(srcfileinfo->lpszFileName, &duphdata,
355 srcfileinfo->lpSecurityAttributes, NULL) == NO_ERROR)
356 {
357 memcpy(pHMHandleData, &duphdata, sizeof(duphdata));
358
359 SetHandleInformation(pHMHandleData, HANDLE_FLAG_INHERIT, (fInherit) ? HANDLE_FLAG_INHERIT : 0);
360
361 SetLastError(ERROR_SUCCESS);
362 return TRUE;
363 }
364 dprintf(("ERROR: DuplicateHandle; CreateFile %s failed -> trying DosDupHandle instead!",
365 srcfileinfo->lpszFileName));
366 //SvL: IE5 setup opens file with DENYREADWRITE, so CreateFile can't
367 // be used for duplicating the handle; try DosDupHandle instead
368 }
369
370 if(!(fdwOptions & DUPLICATE_SAME_ACCESS) && fdwAccess != pHMSrcHandle->dwAccess) {
371 dprintf(("WARNING: DuplicateHandle; app wants different access permission; Not supported!! (%x, %x)", fdwAccess, pHMSrcHandle->dwAccess));
372 }
373
374 pHMHandleData->hHMHandle = 0;
375 rc = OSLibDosDupHandle(pHMSrcHandle->hHMHandle, &pHMHandleData->hHMHandle);
376 if (rc)
377 {
378 dprintf(("ERROR: DuplicateHandle: OSLibDosDupHandle(%s) failed = %u",
379 srcfileinfo->lpszFileName, rc));
380 SetLastError(rc);
381 return FALSE; // ERROR
382 }
383 else {
384 SetHandleInformation(pHMHandleData, HANDLE_FLAG_INHERIT, (fInherit) ? HANDLE_FLAG_INHERIT : 0);
385
386 // Duplicate file information as well -- this is e.g. needed in
387 // CloseHandle() for the FILE_FLAG_DELETE_ON_CLOSE emulation to work
388 if (srcfileinfo) {
389 pHMHandleData->dwUserData =
390 (DWORD) new HMFileInfo(pHMHandleData->hHMHandle,
391 srcfileinfo->lpszFileName, NULL);
392 }
393
394 SetLastError(ERROR_SUCCESS);
395 return TRUE; // OK
396 }
397 }
398 else
399 {
400 dprintf(("ERROR: DuplicateHandle; invalid parameter!!"));
401 SetLastError(ERROR_INVALID_PARAMETER);
402 return FALSE;
403 }
404}
405
406/*****************************************************************************
407 * Name : BOOL HMDeviceFileClass::SetHandleInformation
408 * Purpose : The SetHandleInformation function sets certain properties of an
409 * object handle. The information is specified as a set of bit flags.
410 * Parameters: HANDLE hObject handle to an object
411 * DWORD dwMask specifies flags to change
412 * DWORD dwFlags specifies new values for flags
413 * Variables :
414 * Result : TRUE / FALSE
415 * Remark :
416 * Status :
417 *
418 * Author : SvL
419 *****************************************************************************/
420BOOL HMDeviceFileClass::SetHandleInformation(PHMHANDLEDATA pHMHandleData,
421 DWORD dwMask,
422 DWORD dwFlags)
423{
424 DWORD rc;
425
426 pHMHandleData->dwHandleInformation &= ~dwMask;
427 pHMHandleData->dwHandleInformation |= (dwFlags & dwMask);
428
429 rc = OSLibDosSetFHState(pHMHandleData->hHMHandle,
430 pHMHandleData->dwHandleInformation);
431 if (rc)
432 {
433 dprintf(("ERROR: SetHandleInformation: OSLibDosSetFHState failed with %d", rc));
434
435 SetLastError(rc);
436 return FALSE;
437 }
438
439 SetLastError(ERROR_SUCCESS);
440 return TRUE;
441}
442
443/*****************************************************************************
444 * Name : BOOL HMDeviceFileClass::CloseHandle
445 * Purpose : close the handle
446 * Parameters: PHMHANDLEDATA pHMHandleData
447 * Variables :
448 * Result : API returncode
449 * Remark :
450 * Status :
451 *
452 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
453 *****************************************************************************/
454
455BOOL HMDeviceFileClass::CloseHandle(PHMHANDLEDATA pHMHandleData)
456{
457 HMFileInfo *fileInfo = (HMFileInfo *)pHMHandleData->dwUserData;
458 BOOL bRC;
459
460 dprintfl(("KERNEL32: HMDeviceFileClass::CloseHandle(%08x)\n",
461 pHMHandleData->hHMHandle));
462
463 bRC = OSLibDosClose(pHMHandleData->hHMHandle);
464
465 if(pHMHandleData->dwFlags & FILE_FLAG_DELETE_ON_CLOSE) {
466 //TODO: should only do this after all handles have been closed
467 if(fileInfo) {
468 DeleteFileA(fileInfo->lpszFileName);
469 }
470 }
471 if(fileInfo) {
472 delete fileInfo;
473 }
474 dprintf(("KERNEL32: HMDeviceFileClass::CloseHandle returned %08xh\n",
475 bRC));
476
477 return (DWORD)bRC;
478}
479
480
481/*****************************************************************************
482 * Name : BOOL HMDeviceFileClass::ReadFile
483 * Purpose : read data from handle / device
484 * Parameters: PHMHANDLEDATA pHMHandleData,
485 * LPCVOID lpBuffer,
486 * DWORD nNumberOfBytesToRead,
487 * LPDWORD lpNumberOfBytesRead,
488 * LPOVERLAPPED lpOverlapped
489 * Variables :
490 * Result : Boolean
491 * Remark :
492 * Status :
493 *
494 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
495 *****************************************************************************/
496
497BOOL HMDeviceFileClass::ReadFile(PHMHANDLEDATA pHMHandleData,
498 LPCVOID lpBuffer,
499 DWORD nNumberOfBytesToRead,
500 LPDWORD lpNumberOfBytesRead,
501 LPOVERLAPPED lpOverlapped,
502 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
503{
504 LPVOID lpRealBuf;
505 Win32MemMap *map;
506 DWORD offset, bytesread;
507 BOOL bRC;
508
509 dprintfl(("KERNEL32: HMDeviceFileClass::ReadFile %s(%08x,%08x,%08x,%08x,%08x) - stub?\n",
510 lpHMDeviceName,
511 pHMHandleData,
512 lpBuffer,
513 nNumberOfBytesToRead,
514 lpNumberOfBytesRead,
515 lpOverlapped));
516
517 //SvL: It's legal for this pointer to be NULL
518 if(lpNumberOfBytesRead)
519 *lpNumberOfBytesRead = 0;
520 else
521 lpNumberOfBytesRead = &bytesread;
522
523 if((pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpOverlapped) {
524 dprintf(("FILE_FLAG_OVERLAPPED flag set, but lpOverlapped NULL!!"));
525 SetLastError(ERROR_INVALID_PARAMETER);
526 return FALSE;
527 }
528 if(!(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && lpOverlapped) {
529 dprintf(("Warning: lpOverlapped != NULL & !FILE_FLAG_OVERLAPPED; sync operation"));
530 }
531 if(lpCompletionRoutine) {
532 dprintf(("!WARNING!: lpCompletionRoutine not supported -> fall back to sync IO"));
533 }
534
535 //SvL: DosRead doesn't like writing to memory addresses returned by
536 // DosAliasMem -> search for original memory mapped pointer and use
537 // that one + commit pages if not already present
538 map = Win32MemMapView::findMapByView((ULONG)lpBuffer, &offset, MEMMAP_ACCESS_WRITE);
539 if(map) {
540 lpRealBuf = (LPVOID)((ULONG)map->getMappingAddr() + offset);
541 DWORD nrpages = nNumberOfBytesToRead/4096;
542 if((nNumberOfBytesToRead+offset) & 0xfff)
543 nrpages++;
544
545 map->commitRange((ULONG)lpBuffer, offset & ~0xfff, TRUE, nrpages);
546 map->Release();
547 }
548 else lpRealBuf = (LPVOID)lpBuffer;
549
550 //If this file is also used in a memory map somewhere, then we need
551 //to tell the map to flush all modified contents to disk right NOW
552 map = Win32MemMap::findMapByFile(pHMHandleData->hWin32Handle);
553 if(map) {
554 DWORD curpos = SetFilePointer(pHMHandleData, 0, NULL, FILE_CURRENT);
555
556 dprintf(("Flush memory maps to disk before reading!!"));
557 map->flushView(MMAP_FLUSHVIEW_ALL, curpos, nNumberOfBytesToRead);
558 map->Release();
559 }
560
561 if(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) {
562 dprintf(("ERROR: Overlapped IO not yet implememented!!"));
563 }
564// else {
565 bRC = OSLibDosRead(pHMHandleData->hHMHandle,
566 (PVOID)lpRealBuf,
567 nNumberOfBytesToRead,
568 lpNumberOfBytesRead);
569// }
570
571 if(bRC == 0) {
572 dprintf(("KERNEL32: HMDeviceFileClass::ReadFile returned %08xh %x\n",
573 bRC, GetLastError()));
574 dprintf(("%x -> %d", lpBuffer, IsBadWritePtr((LPVOID)lpBuffer, nNumberOfBytesToRead)));
575 }
576
577 return bRC;
578}
579
580
581/*****************************************************************************
582 * Name : BOOL HMDeviceFileClass::WriteFile
583 * Purpose : write data to handle / device
584 * Parameters: PHMHANDLEDATA pHMHandleData,
585 * LPCVOID lpBuffer,
586 * DWORD nNumberOfBytesToWrite,
587 * LPDWORD lpNumberOfBytesWritten,
588 * LPOVERLAPPED lpOverlapped
589 * Variables :
590 * Result : Boolean
591 * Remark :
592 * Status :
593 *
594 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
595 *****************************************************************************/
596
597BOOL HMDeviceFileClass::WriteFile(PHMHANDLEDATA pHMHandleData,
598 LPCVOID lpBuffer,
599 DWORD nNumberOfBytesToWrite,
600 LPDWORD lpNumberOfBytesWritten,
601 LPOVERLAPPED lpOverlapped,
602 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
603{
604 LPVOID lpRealBuf;
605 Win32MemMap *map;
606 DWORD offset, byteswritten;
607 BOOL bRC;
608
609 dprintfl(("KERNEL32: HMDeviceFileClass::WriteFile %s(%08x,%08x,%08x,%08x,%08x) - stub?\n",
610 lpHMDeviceName,
611 pHMHandleData,
612 lpBuffer,
613 nNumberOfBytesToWrite,
614 lpNumberOfBytesWritten,
615 lpOverlapped));
616
617 //SvL: It's legal for this pointer to be NULL
618 if(lpNumberOfBytesWritten)
619 *lpNumberOfBytesWritten = 0;
620 else
621 lpNumberOfBytesWritten = &byteswritten;
622
623 if((pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpOverlapped) {
624 dprintf(("FILE_FLAG_OVERLAPPED flag set, but lpOverlapped NULL!!"));
625 SetLastError(ERROR_INVALID_PARAMETER);
626 return FALSE;
627 }
628 if(!(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && lpOverlapped) {
629 dprintf(("Warning: lpOverlapped != NULL & !FILE_FLAG_OVERLAPPED; sync operation"));
630 }
631
632 //SvL: DosWrite doesn't like reading from memory addresses returned by
633 // DosAliasMem -> search for original memory mapped pointer and use
634 // that one + commit pages if not already present
635 map = Win32MemMapView::findMapByView((ULONG)lpBuffer, &offset, MEMMAP_ACCESS_READ);
636 if(map) {
637 lpRealBuf = (LPVOID)((ULONG)map->getMappingAddr() + offset);
638 DWORD nrpages = nNumberOfBytesToWrite/4096;
639 if((nNumberOfBytesToWrite+offset) & 0xfff)
640 nrpages++;
641
642 map->commitRange((ULONG)lpBuffer, offset & ~0xfff, FALSE, nrpages);
643 map->Release();
644 }
645 else lpRealBuf = (LPVOID)lpBuffer;
646
647 if(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) {
648 dprintf(("ERROR: Overlapped IO not yet implememented!!"));
649 }
650// else {
651 bRC = OSLibDosWrite(pHMHandleData->hHMHandle,
652 (PVOID)lpRealBuf,
653 nNumberOfBytesToWrite,
654 lpNumberOfBytesWritten);
655// }
656
657 if (bRC) {
658 //If this file is also used in a memory map somewhere, then we need
659 //to invalidate memory pages that we just wrote
660 DWORD curfilepos;
661 map = Win32MemMap::findMapByFile(pHMHandleData->hWin32Handle);
662 if(map) {
663 curfilepos = SetFilePointer(pHMHandleData, 0, NULL, FILE_CURRENT);
664
665 dprintf(("Invalidate memory map after file writing!!"));
666 map->invalidatePages(curfilepos, *lpNumberOfBytesWritten);
667 map->Release();
668 }
669 }
670
671 dprintf(("KERNEL32: HMDeviceFileClass::WriteFile returned %08xh\n",
672 bRC));
673
674 return bRC;
675}
676
677
678/*****************************************************************************
679 * Name : DWORD HMDeviceFileClass::GetFileType
680 * Purpose : determine the handle type
681 * Parameters: PHMHANDLEDATA pHMHandleData
682 * Variables :
683 * Result : API returncode
684 * Remark :
685 * Status :
686 *
687 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
688 *****************************************************************************/
689
690DWORD HMDeviceFileClass::GetFileType(PHMHANDLEDATA pHMHandleData)
691{
692 dprintfl(("KERNEL32: HMDeviceFileClass::GetFileType %s(%08x)\n",
693 lpHMDeviceName,
694 pHMHandleData));
695
696 return FILE_TYPE_DISK;
697}
698
699
700/*****************************************************************************
701 * Name : DWORD HMDeviceFileClass::GetFileInformationByHandle
702 * Purpose : determine the handle type
703 * Parameters: PHMHANDLEDATA pHMHandleData
704 * BY_HANDLE_FILE_INFORMATION* pHFI
705 * Variables :
706 * Result : API returncode
707 * Remark :
708 * Status :
709 *
710 * Author : Patrick Haller [Wed, 1999/06/17 20:44]
711 *****************************************************************************/
712
713DWORD HMDeviceFileClass::GetFileInformationByHandle(PHMHANDLEDATA pHMHandleData,
714 BY_HANDLE_FILE_INFORMATION* pHFI)
715{
716 dprintfl(("KERNEL32: HMDeviceFileClass::GetFileInformationByHandle %s(%08xh,%08xh)\n",
717 lpHMDeviceName, pHMHandleData, pHFI));
718
719 HMFileInfo *fileInfo = (HMFileInfo *)pHMHandleData->dwUserData;
720 if(OSLibDosGetFileInformationByHandle(fileInfo->lpszFileName,
721 pHMHandleData->hHMHandle,
722 pHFI))
723 {
724 return TRUE;
725 }
726 dprintf(("GetFileInformationByHandle failed with error %d", GetLastError()));
727 return FALSE;
728
729}
730
731
732/*****************************************************************************
733 * Name : BOOL HMDeviceFileClass::SetEndOfFile
734 * Purpose : set end of file marker
735 * Parameters: PHMHANDLEDATA pHMHandleData
736 * Variables :
737 * Result : API returncode
738 * Remark :
739 * Status :
740 *
741 * Author : Patrick Haller [Wed, 1999/06/17 20:44]
742 *****************************************************************************/
743
744BOOL HMDeviceFileClass::SetEndOfFile(PHMHANDLEDATA pHMHandleData)
745{
746 dprintfl(("KERNEL32: HMDeviceFileClass::SetEndOfFile %s(%08xh)\n",
747 lpHMDeviceName,
748 pHMHandleData));
749
750 if(OSLibDosSetEndOfFile(pHMHandleData->hHMHandle)) {
751 return TRUE;
752 }
753 dprintf(("SetEndOfFile failed with error %d", GetLastError()));
754 return FALSE;
755}
756
757//******************************************************************************
758/*****************************************************************************
759 * Name : BOOL HMDeviceFileClass::SetFileTime
760 * Purpose : set file time
761 * Parameters: PHMHANDLEDATA pHMHandleData
762 * PFILETIME pFT1
763 * PFILETIME pFT2
764 * PFILETIME pFT3
765 * Variables :
766 * Result : API returncode
767 * Remark :
768 * Status :
769 *
770 * Author : Patrick Haller [Wed, 1999/06/17 20:44] mod. DT
771 *****************************************************************************/
772
773BOOL HMDeviceFileClass::SetFileTime(PHMHANDLEDATA pHMHandleData,
774 LPFILETIME pFT1,
775 LPFILETIME pFT2,
776 LPFILETIME pFT3)
777{
778 dprintfl(("KERNEL32: HMDeviceFileClass::SetFileTime %s(%08xh,%08xh,%08xh,%08xh)\n",
779 lpHMDeviceName, pHMHandleData, pFT1, pFT2, pFT3));
780
781 if(OSLibDosSetFileTime(pHMHandleData->hHMHandle, pFT1, pFT2, pFT3)) return TRUE;
782
783 dprintf(("SetFileTime failed with error %d", GetLastError()));
784 return FALSE;
785}
786
787/*****************************************************************************
788 * Name : BOOL HMDeviceFileClass::GetFileTime
789 * Purpose : get file time
790 * Parameters: PHMHANDLEDATA pHMHandleData
791 * PFILETIME pFT1
792 * PFILETIME pFT2
793 * PFILETIME pFT3
794 * Variables :
795 * Result : API returncode
796 * Remark :
797 * Status :
798 *
799 * Author : SvL mod. DT
800 *****************************************************************************/
801
802BOOL HMDeviceFileClass::GetFileTime(PHMHANDLEDATA pHMHandleData,
803 LPFILETIME pFT1,
804 LPFILETIME pFT2,
805 LPFILETIME pFT3)
806{
807 if(!pFT1 && !pFT2 && !pFT3) {//TODO: does NT do this?
808 dprintf(("ERROR: GetFileTime: invalid parameter!"));
809 SetLastError(ERROR_INVALID_PARAMETER);
810 return FALSE;
811 }
812
813 if(OSLibDosGetFileTime(pHMHandleData->hHMHandle, pFT1, pFT2, pFT3)) return TRUE;
814 dprintf(("GetFileTime failed with error %d", GetLastError()));
815 return FALSE;
816}
817
818/*****************************************************************************
819 * Name : DWORD HMDeviceFileClass::GetFileSize
820 * Purpose : set file time
821 * Parameters: PHMHANDLEDATA pHMHandleData
822 * PDWORD pSize
823 * Variables :
824 * Result : API returncode
825 * Remark :
826 * Status :
827 *
828 * Author : Patrick Haller [Wed, 1999/06/17 20:44]
829 *****************************************************************************/
830
831DWORD HMDeviceFileClass::GetFileSize(PHMHANDLEDATA pHMHandleData,
832 PDWORD lpdwFileSizeHigh)
833{
834 dprintfl(("KERNEL32: HMDeviceFileClass::GetFileSize %s(%08xh,%08xh)\n",
835 lpHMDeviceName,
836 pHMHandleData,
837 lpdwFileSizeHigh));
838
839 if(lpdwFileSizeHigh)
840 *lpdwFileSizeHigh = 0;
841
842 return OSLibDosGetFileSize(pHMHandleData->hHMHandle, lpdwFileSizeHigh);
843}
844
845/*****************************************************************************
846 * Name : DWORD HMDeviceFileClass::SetFilePointer
847 * Purpose : set file pointer
848 * Parameters: PHMHANDLEDATA pHMHandleData
849 * LONG lDistanceToMove
850 * PLONG lpDistanceToMoveHigh
851 * DWORD dwMoveMethod
852 * Variables :
853 * Result : API returncode
854 * Remark :
855 * Status :
856 *
857 * Author : Patrick Haller [Wed, 1999/06/17 20:44]
858 *****************************************************************************/
859
860DWORD HMDeviceFileClass::SetFilePointer(PHMHANDLEDATA pHMHandleData,
861 LONG lDistanceToMove,
862 PLONG lpDistanceToMoveHigh,
863 DWORD dwMoveMethod)
864{
865 DWORD ret;
866 HMFileInfo *fileInfo = (HMFileInfo *)pHMHandleData->dwUserData;
867
868 dprintfl(("KERNEL32: HMDeviceFileClass::SetFilePointer %s(%08xh,%08xh,%08xh,%08xh)\n",
869 lpHMDeviceName,
870 pHMHandleData,
871 lDistanceToMove,
872 lpDistanceToMoveHigh,
873 dwMoveMethod));
874
875 if(fileInfo && fileInfo->dwLXOffset)
876 {
877 switch(dwMoveMethod)
878 {
879 case FILE_BEGIN:
880 dprintf(("SetFilePointer FILE_BEGIN (LX) -> change offset from %x to %x", lDistanceToMove, lDistanceToMove+fileInfo->dwLXOffset));
881 lDistanceToMove += fileInfo->dwLXOffset;
882 break;
883
884 case FILE_END:
885 //Could overshoot the virtual beginning of the PE file
886 lDistanceToMove -= MAGIC_STUBEXE_SIZE;
887 dprintf(("SetFilePointer FILE_END -> might be dangerous!!"));
888 break;
889
890 }
891 }
892
893 ret = OSLibDosSetFilePointer(pHMHandleData->hHMHandle,
894 lDistanceToMove,
895 (DWORD *)lpDistanceToMoveHigh,
896 dwMoveMethod);
897
898 if(ret == -1) {
899 dprintf(("SetFilePointer failed (error = %d)", GetLastError()));
900 }
901 return ret;
902}
903
904
905/*****************************************************************************
906 * Name : BOOL HMDeviceFileClass::LockFile
907 * Purpose : file locking
908 * Parameters: PHMHANDLEDATA pHMHandleData
909 * DWORD arg2
910 * DWORD arg3
911 * DWORD arg4
912 * DWORD arg5
913 * Variables :
914 * Result : API returncode
915 * Remark :
916 * Status :
917 *
918 * Author : Patrick Haller [Wed, 1999/06/17 20:44]
919 *****************************************************************************/
920
921BOOL HMDeviceFileClass::LockFile(PHMHANDLEDATA pHMHandleData,
922 DWORD dwFileOffsetLow,
923 DWORD dwFileOffsetHigh,
924 DWORD cbLockLow,
925 DWORD cbLockHigh)
926{
927 dprintfl(("KERNEL32: HMDeviceFileClass::LockFile %s(%08xh,%08xh,%08xh,%08xh,%08xh)\n",
928 lpHMDeviceName,
929 pHMHandleData,
930 dwFileOffsetLow,
931 dwFileOffsetHigh,
932 cbLockLow,
933 cbLockHigh));
934
935 return OSLibDosLockFile(pHMHandleData->hHMHandle,
936 LOCKFILE_EXCLUSIVE_LOCK,
937 dwFileOffsetLow,
938 dwFileOffsetHigh,
939 cbLockLow,
940 cbLockHigh,
941 NULL);
942}
943
944/*****************************************************************************
945 * Name : DWORD HMDeviceFileClass::LockFileEx
946 * Purpose : file locking
947 * Parameters: PHMHANDLEDATA pHMHandleData
948 * DWORD dwFlags
949 * DWORD dwReserved
950 * DWORD nNumberOfBytesToLockLow
951 * DWORD nNumberOfBytesToLockHigh
952 * LPOVERLAPPED lpOverlapped
953 * Variables :
954 * Result : API returncode
955 * Remark :
956 * Status :
957 *
958 * Author : Patrick Haller [Wed, 1999/06/17 20:44]
959 *****************************************************************************/
960
961BOOL HMDeviceFileClass::LockFileEx(PHMHANDLEDATA pHMHandleData,
962 DWORD dwFlags,
963 DWORD dwReserved,
964 DWORD nNumberOfBytesToLockLow,
965 DWORD nNumberOfBytesToLockHigh,
966 LPOVERLAPPED lpOverlapped)
967{
968
969 dprintfl(("KERNEL32: HMDeviceFileClass::LockFileEx %s(%08xh,%08xh,%08xh,%08xh,%08xh,%08xh) not completely implemented!",
970 lpHMDeviceName,
971 pHMHandleData,
972 dwFlags,
973 dwReserved,
974 nNumberOfBytesToLockLow,
975 nNumberOfBytesToLockHigh,
976 lpOverlapped));
977
978
979 return(OSLibDosLockFile(pHMHandleData->hHMHandle,
980 dwFlags,
981 lpOverlapped->Offset,
982 lpOverlapped->OffsetHigh,
983 nNumberOfBytesToLockLow,
984 nNumberOfBytesToLockHigh,
985 lpOverlapped));
986}
987
988
989/*****************************************************************************
990 * Name : DWORD HMDeviceFileClass::UnlockFile
991 * Purpose : file locking
992 * Parameters: PHMHANDLEDATA pHMHandleData
993 * DWORD arg2
994 * DWORD arg3
995 * DWORD arg4
996 * DWORD arg5
997 * Variables :
998 * Result : API returncode
999 * Remark :
1000 * Status :
1001 *
1002 * Author : Patrick Haller [Wed, 1999/06/17 20:44]
1003 *****************************************************************************/
1004
1005BOOL HMDeviceFileClass::UnlockFile(PHMHANDLEDATA pHMHandleData,
1006 DWORD dwFileOffsetLow,
1007 DWORD dwFileOffsetHigh,
1008 DWORD cbLockLow,
1009 DWORD cbLockHigh)
1010{
1011 dprintfl(("KERNEL32: HMDeviceFileClass::UnlockFile %s(%08xh,%08xh,%08xh,%08xh,%08xh)\n",
1012 lpHMDeviceName,
1013 pHMHandleData,
1014 dwFileOffsetLow,
1015 dwFileOffsetHigh,
1016 cbLockLow,
1017 cbLockHigh));
1018
1019 return OSLibDosUnlockFile(pHMHandleData->hHMHandle,
1020 dwFileOffsetLow,
1021 dwFileOffsetHigh,
1022 cbLockLow,
1023 cbLockHigh,
1024 NULL);
1025}
1026
1027
1028
1029/*****************************************************************************
1030 * Name : DWORD HMDeviceFileClass::UnlockFileEx
1031 * Purpose : file locking
1032 * Parameters: PHMHANDLEDATA pHMHandleData
1033 * DWORD dwFlags
1034 * DWORD dwReserved
1035 * DWORD nNumberOfBytesToLockLow
1036 * DWORD nNumberOfBytesToLockHigh
1037 * LPOVERLAPPED lpOverlapped
1038 * Variables :
1039 * Result : API returncode
1040 * Remark :
1041 * Status :
1042 *
1043 * Author : Patrick Haller [Wed, 1999/06/17 20:44]
1044 *****************************************************************************/
1045
1046BOOL HMDeviceFileClass::UnlockFileEx(PHMHANDLEDATA pHMHandleData,
1047 DWORD dwReserved,
1048 DWORD nNumberOfBytesToLockLow,
1049 DWORD nNumberOfBytesToLockHigh,
1050 LPOVERLAPPED lpOverlapped)
1051{
1052
1053 dprintfl(("KERNEL32: HMDeviceFileClass::UnlockFileEx %s(%08xh,%08xh,%08xh,%08xh,%08xh) not completely implemented!",
1054 lpHMDeviceName,
1055 pHMHandleData,
1056 dwReserved,
1057 nNumberOfBytesToLockLow,
1058 nNumberOfBytesToLockHigh,
1059 lpOverlapped));
1060
1061
1062 return(OSLibDosUnlockFile(pHMHandleData->hHMHandle,
1063 lpOverlapped->Offset,
1064 lpOverlapped->OffsetHigh,
1065 nNumberOfBytesToLockLow,
1066 nNumberOfBytesToLockHigh,
1067 lpOverlapped));
1068}
1069
1070
1071/*****************************************************************************
1072 * Name : DWORD HMDeviceFileClass::FlushFileBuffers
1073 * Purpose : flush the buffers of a file
1074 * Parameters: PHMHANDLEDATA pHMHandleData
1075 * Variables :
1076 * Result : API returncode
1077 * Remark :
1078 * Status :
1079 *
1080 * Author : Patrick Haller [Wed, 1999/06/17 20:44]
1081 *****************************************************************************/
1082
1083BOOL HMDeviceFileClass::FlushFileBuffers(PHMHANDLEDATA pHMHandleData)
1084{
1085 dprintfl(("KERNEL32: HMDeviceFileClass:FlushFileBuffers(%08xh)\n",
1086 pHMHandleData->hHMHandle));
1087
1088 return(OSLibDosFlushFileBuffers(pHMHandleData->hHMHandle));
1089}
1090
1091
1092/*****************************************************************************
1093 * Name : DWORD HMDeviceFileClass::GetOverlappedResult
1094 * Purpose : asynchronus I/O
1095 * Parameters: PHMHANDLEDATA pHMHandleData
1096 * LPOVERLAPPED arg2
1097 * LPDWORD arg3
1098 * BOOL arg4
1099 * Variables :
1100 * Result : API returncode
1101 * Remark :
1102 * Status :
1103 *
1104 * Author : Patrick Haller [Wed, 1999/06/17 20:44]
1105 *****************************************************************************/
1106
1107BOOL HMDeviceFileClass::GetOverlappedResult(PHMHANDLEDATA pHMHandleData,
1108 LPOVERLAPPED arg2,
1109 LPDWORD arg3,
1110 BOOL arg4)
1111{
1112 dprintfl(("KERNEL32-WARNING: HMDeviceFileClass::GetOverlappedResult(%08xh,%08xh,%08xh,%08xh) STUB!!",
1113 pHMHandleData->hHMHandle,
1114 arg2,
1115 arg3,
1116 arg4));
1117
1118 return FALSE;
1119// return(O32_GetOverlappedResult(pHMHandleData->hHMHandle,
1120// arg2,
1121// arg3,
1122// arg4));
1123}
1124/******************************************************************************
1125 * Name : DWORD HMDeviceFileClass::GetFileNameFromHandle
1126 * Purpose : the name of the file associated with the system handle (if any)
1127 * Parameters: PHMHANDLEDATA pHMHandleData
1128 * Variables :
1129 * Result : BOOLEAN
1130 * Remark :
1131 * Status :
1132 *
1133 * Author : SvL
1134 ******************************************************************************/
1135BOOL HMDeviceFileClass::GetFileNameFromHandle(PHMHANDLEDATA pHMHandleData,
1136 LPSTR lpszFileName, DWORD cbFileName)
1137{
1138 HMFileInfo *fileInfo = (HMFileInfo *)pHMHandleData->dwUserData;
1139
1140 if(fileInfo == NULL || strlen(fileInfo->lpszFileName) >= cbFileName) {
1141 if(fileInfo) DebugInt3();
1142 return FALSE;
1143 }
1144 strcpy(lpszFileName, fileInfo->lpszFileName);
1145
1146 return TRUE;
1147}
1148
1149//******************************************************************************
1150//******************************************************************************
1151// File information handle class
1152//
1153// When the application opens a file with CreateFile and 0 for desired access,
1154// then we need to create a handle with limited access.
1155//
1156// MSDN:
1157//
1158// If this parameter is zero, the application can query file and device attributes
1159// without accessing the device. This is useful if an application wants to determine
1160// the size of a floppy disk drive and the formats it supports without requiring
1161// a floppy in the drive. It can also be used to test for the file's or directory's
1162// existence without opening it for read or write access.
1163//
1164//******************************************************************************
1165//******************************************************************************
1166
1167/******************************************************************************
1168 * Name : DWORD HMDeviceInfoFileClass::CreateFile
1169 * Purpose : this is called from the handle manager if a CreateFile() is
1170 * performed on a handle
1171 * Parameters: LPCSTR lpFileName name of the file / device
1172 * PHMHANDLEDATA pHMHandleData data of the NEW handle
1173 * PVOID lpSecurityAttributes ignored
1174 * PHMHANDLEDATA pHMHandleDataTemplate data of the template handle
1175 * Variables :
1176 * Result :
1177 * Remark :
1178 * Status : NO_ERROR - API succeeded
1179 * other - what is to be set in SetLastError
1180 *
1181 * Author : SvL
1182 *****************************************************************************/
1183DWORD HMDeviceInfoFileClass::CreateFile (LPCSTR lpFileName,
1184 PHMHANDLEDATA pHMHandleData,
1185 PVOID lpSecurityAttributes,
1186 PHMHANDLEDATA pHMHandleDataTemplate)
1187{
1188 char filepath[260];
1189 DWORD dwAttr;
1190
1191 dprintfl(("KERNEL32: HMDeviceInfoFileClass::CreateFile %s(%s,%08x,%08x,%08x)\n",
1192 lpHMDeviceName,
1193 lpFileName,
1194 pHMHandleData,
1195 lpSecurityAttributes,
1196 pHMHandleDataTemplate));
1197
1198 ParsePath(lpFileName, filepath, sizeof(filepath));
1199
1200 //convert to long file name if in 8.3 hashed format
1201 GetLongPathNameA(filepath, filepath, sizeof(filepath));
1202 lpFileName = filepath;
1203
1204
1205 dwAttr = GetFileAttributesA(lpFileName);
1206 if(dwAttr == -1) {
1207 return GetLastError();
1208 }
1209
1210 pHMHandleData->dwUserData = (DWORD) new HMFileInfo(0, (LPSTR)lpFileName, lpSecurityAttributes);
1211 pHMHandleData->hHMHandle = 0x8000000;
1212 return (NO_ERROR);
1213
1214}
1215/******************************************************************************
1216 * Name : BOOL HMDeviceFileClass::CloseHandle
1217 * Purpose : close the handle
1218 * Parameters: PHMHANDLEDATA pHMHandleData
1219 * Variables :
1220 * Result : API returncode
1221 * Remark :
1222 * Status :
1223 *
1224 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
1225 *****************************************************************************/
1226BOOL HMDeviceInfoFileClass::CloseHandle(PHMHANDLEDATA pHMHandleData)
1227{
1228 HMFileInfo *fileInfo = (HMFileInfo *)pHMHandleData->dwUserData;
1229
1230 dprintfl(("KERNEL32: HMDeviceInfoFileClass::CloseHandle(%08x)\n",
1231 pHMHandleData->hHMHandle));
1232
1233 if(fileInfo) {
1234 delete fileInfo;
1235 }
1236 return TRUE;
1237}
1238/******************************************************************************
1239 * Name : BOOL HMDeviceInfoFileClass::GetFileTime
1240 * Purpose : Get file time
1241 * Parameters: PHMHANDLEDATA pHMHandleData
1242 * PFILETIME pFT1
1243 * PFILETIME pFT2
1244 * PFILETIME pFT3
1245 * Variables :
1246 * Result : API returncode
1247 * Remark :
1248 * Status :
1249 *
1250 * Author : SvL
1251 *****************************************************************************/
1252BOOL HMDeviceInfoFileClass::GetFileTime (PHMHANDLEDATA pHMHandleData,
1253 LPFILETIME pFT1,
1254 LPFILETIME pFT2,
1255 LPFILETIME pFT3)
1256{
1257 HMFileInfo *fileInfo = (HMFileInfo *)pHMHandleData->dwUserData;
1258
1259 if(!pFT1 && !pFT2 && !pFT3) {//TODO: does NT do this?
1260 dprintf(("ERROR: GetFileTime: invalid parameter!"));
1261 SetLastError(ERROR_INVALID_PARAMETER);
1262 return FALSE;
1263 }
1264 WIN32_FIND_DATAA finddata;
1265 HANDLE hFind;
1266
1267 hFind = FindFirstFileA(fileInfo->lpszFileName, &finddata);
1268 if(hFind == INVALID_HANDLE_VALUE) {
1269 return GetLastError();
1270 }
1271 if(pFT1) {
1272 *pFT1 = finddata.ftCreationTime;
1273 }
1274 if(pFT2) {
1275 *pFT2 = finddata.ftLastAccessTime;
1276 }
1277 if(pFT3) {
1278 *pFT3 = finddata.ftLastWriteTime;
1279 }
1280 FindClose(hFind);
1281 SetLastError(ERROR_SUCCESS);
1282 return TRUE;
1283}
1284/******************************************************************************
1285 * Name : DWORD HMDeviceInfoFileClass::GetFileSize
1286 * Purpose : get file size
1287 * Parameters: PHMHANDLEDATA pHMHandleData
1288 * PDWORD pSize
1289 * Variables :
1290 * Result : API returncode
1291 * Remark : Doesn't fail for directories; just returns 0 (verified in NT4, SP6)
1292 * Status :
1293 *
1294 * Author : SvL
1295 *****************************************************************************/
1296DWORD HMDeviceInfoFileClass::GetFileSize(PHMHANDLEDATA pHMHandleData,
1297 PDWORD lpdwFileSizeHigh)
1298{
1299 HMFileInfo *fileInfo = (HMFileInfo *)pHMHandleData->dwUserData;
1300
1301 SetLastError(ERROR_SUCCESS);
1302
1303 if(lpdwFileSizeHigh)
1304 *lpdwFileSizeHigh = 0;
1305
1306 if(fileInfo == NULL) {
1307 DebugInt3();
1308 SetLastError(ERROR_INVALID_PARAMETER); //TODO
1309 return -1; //INVALID_FILE_SIZE;
1310 }
1311
1312 WIN32_FIND_DATAA finddata;
1313 HANDLE hFind;
1314
1315 hFind = FindFirstFileA(fileInfo->lpszFileName, &finddata);
1316 if(hFind == INVALID_HANDLE_VALUE) {
1317 return GetLastError();
1318 }
1319 if(lpdwFileSizeHigh) {
1320 *lpdwFileSizeHigh = finddata.nFileSizeHigh;
1321 }
1322 FindClose(hFind);
1323
1324 if(fileInfo->dwLXOffset)
1325 {
1326 //subtract the LX header and magic qword from the file size
1327 dprintf(("GetFileSize (LX) -> change size from %x to %x", finddata.nFileSizeLow, finddata.nFileSizeLow-fileInfo->dwLXOffset-MAGIC_STUBEXE_SIZE));
1328 finddata.nFileSizeLow -= (fileInfo->dwLXOffset+MAGIC_STUBEXE_SIZE);
1329 }
1330 return finddata.nFileSizeLow;
1331}
1332/******************************************************************************
1333 * Name : DWORD HMDeviceFileClass::GetFileNameFromHandle
1334 * Purpose : the name of the file associated with the system handle (if any)
1335 * Parameters: PHMHANDLEDATA pHMHandleData
1336 * Variables :
1337 * Result : BOOLEAN
1338 * Remark :
1339 * Status :
1340 *
1341 * Author : SvL
1342 ******************************************************************************/
1343BOOL HMDeviceInfoFileClass::GetFileNameFromHandle(PHMHANDLEDATA pHMHandleData,
1344 LPSTR lpszFileName, DWORD cbFileName)
1345{
1346 HMFileInfo *fileInfo = (HMFileInfo *)pHMHandleData->dwUserData;
1347
1348 if(fileInfo == NULL || strlen(fileInfo->lpszFileName) >= cbFileName) {
1349 if(fileInfo) DebugInt3();
1350 return FALSE;
1351 }
1352 strcpy(lpszFileName, fileInfo->lpszFileName);
1353
1354 return TRUE;
1355}
1356/******************************************************************************
1357 * Name : DWORD HMDeviceFileClass::GetFileType
1358 * Purpose : determine the handle type
1359 * Parameters: PHMHANDLEDATA pHMHandleData
1360 * Variables :
1361 * Result : API returncode
1362 * Remark : Returns FILE_TYPE_DISK for both files and directories
1363 * Status :
1364 *
1365 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
1366 ******************************************************************************/
1367DWORD HMDeviceInfoFileClass::GetFileType(PHMHANDLEDATA pHMHandleData)
1368{
1369 dprintfl(("KERNEL32: HMDeviceInfoFileClass::GetFileType %s(%08x)\n",
1370 lpHMDeviceName,
1371 pHMHandleData));
1372
1373 return FILE_TYPE_DISK;
1374}
1375//******************************************************************************
1376//******************************************************************************
1377HMFileInfo::HMFileInfo(HANDLE hFile, LPSTR lpszFileName, PVOID lpSecurityAttributes)
1378{
1379 // get the full path (this is necessary in particular for GetFileInformationByHandle)
1380 char fullPath[260];
1381 if (!OSLibDosQueryPathInfo(lpszFileName, FIL_QUERYFULLNAME, fullPath, sizeof(fullPath))) {
1382 lpszFileName = fullPath;
1383 }
1384
1385 this->lpszFileName = (LPSTR)malloc(strlen(lpszFileName)+1);
1386 if(!this->lpszFileName) {
1387 DebugInt3();
1388 }
1389 strcpy(this->lpszFileName, lpszFileName);
1390 this->lpSecurityAttributes = lpSecurityAttributes;
1391 dwLXOffset = 0;
1392
1393 //Only check files that end with .exe for now; they might be prepended with
1394 //an LX header. We need to skip that to present the original file to the
1395 //caller
1396 if(hFile && !stricmp(lpszFileName + strlen(lpszFileName) - 4, ".EXE"))
1397 {
1398 ULONG action, ulRead, signature, ulFileSize;
1399 ULONG magic[2];
1400 IMAGE_DOS_HEADER doshdr;
1401
1402 //read dos header
1403 if(!OSLibDosRead(hFile, (LPVOID)&doshdr, sizeof(doshdr), &ulRead)) {
1404 goto failure;
1405 }
1406 if(OSLibDosSetFilePointer(hFile, doshdr.e_lfanew, NULL, FILE_BEGIN) != doshdr.e_lfanew) {
1407 goto failure;
1408 }
1409 //read signature dword
1410 if(!OSLibDosRead(hFile, (LPVOID)&signature, sizeof(signature), &ulRead)) {
1411 goto failure;
1412 }
1413
1414 //Make sure it's an LX executable before continueing
1415 if(doshdr.e_magic != IMAGE_DOS_SIGNATURE || (WORD)signature != IMAGE_OS2_SIGNATURE_LX)
1416 {
1417 goto failure;
1418 }
1419
1420 //magic signature located at 8 bytes from file end
1421 if(OSLibDosSetFilePointer(hFile, -8, NULL, FILE_END) == -1) {
1422 goto failure;
1423 }
1424 //read magic signature + pe offset
1425 if(!OSLibDosRead(hFile, (LPVOID)&magic[0], sizeof(magic), &ulRead)) {
1426 goto failure;
1427 }
1428 if(magic[0] != MAGIC_STUBEXE_SIGNATURE || magic[1] > ulFileSize) {
1429 goto failure;
1430 }
1431 //this is the offset of the PE image inside our LX executable
1432 dwLXOffset = magic[1];
1433
1434 dprintf(("LX wrapper: PE file %s starts at %x", lpszFileName, dwLXOffset));
1435 //reset file pointer to PE image start
1436 if(OSLibDosSetFilePointer(hFile, dwLXOffset, NULL, FILE_BEGIN) != dwLXOffset) {
1437 DebugInt3();
1438 }
1439 goto end;
1440
1441failure:
1442 //reset file pointer to file start
1443 if(OSLibDosSetFilePointer(hFile, 0, NULL, FILE_BEGIN) != 0) {
1444 DebugInt3();
1445 }
1446 }
1447end:
1448 return;
1449}
1450//******************************************************************************
1451//******************************************************************************
1452HMFileInfo::~HMFileInfo()
1453{
1454 if(lpszFileName) {
1455 free(lpszFileName);
1456 lpszFileName = NULL;
1457 }
1458}
1459
1460//*****************************************************************************
1461//Parses and copies path
1462//OpenFile in NT4, SP6 accepts double (or more) backslashes as separators for directories!
1463//(OS/2 doesn't)
1464//Girotel 2.0 (Dutch banking app) seems to depend on this behaviour
1465//*****************************************************************************
1466static void ParsePath(LPCSTR lpszFileName, LPSTR lpszParsedFileName, DWORD length)
1467{
1468 int i=0;
1469
1470 while(*lpszFileName != 0 && i < length-1) {
1471 *lpszParsedFileName++ = *lpszFileName;
1472 if(*lpszFileName == '\\') {
1473 while(*lpszFileName == '\\') {
1474 lpszFileName++;
1475 }
1476 }
1477 else {
1478 lpszFileName++;
1479 }
1480 i++;
1481 }
1482 *lpszParsedFileName = 0;
1483}
1484//******************************************************************************
1485//******************************************************************************
Note: See TracBrowser for help on using the repository browser.