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

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

kernel32: Fixed: Closing a duplicate of a handle opened with FILE_FLAG_DELETE_ON_CLOSE would not perform file deletion if that duplicate was the last reference to the file (e.g. closed after the original handle).

File size: 50.5 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 }
559
560 if(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) {
561 dprintf(("ERROR: Overlapped IO not yet implememented!!"));
562 }
563// else {
564 bRC = OSLibDosRead(pHMHandleData->hHMHandle,
565 (PVOID)lpRealBuf,
566 nNumberOfBytesToRead,
567 lpNumberOfBytesRead);
568// }
569
570 if(bRC == 0) {
571 dprintf(("KERNEL32: HMDeviceFileClass::ReadFile returned %08xh %x\n",
572 bRC, GetLastError()));
573 dprintf(("%x -> %d", lpBuffer, IsBadWritePtr((LPVOID)lpBuffer, nNumberOfBytesToRead)));
574 }
575
576 return bRC;
577}
578
579
580/*****************************************************************************
581 * Name : BOOL HMDeviceFileClass::WriteFile
582 * Purpose : write data to handle / device
583 * Parameters: PHMHANDLEDATA pHMHandleData,
584 * LPCVOID lpBuffer,
585 * DWORD nNumberOfBytesToWrite,
586 * LPDWORD lpNumberOfBytesWritten,
587 * LPOVERLAPPED lpOverlapped
588 * Variables :
589 * Result : Boolean
590 * Remark :
591 * Status :
592 *
593 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
594 *****************************************************************************/
595
596BOOL HMDeviceFileClass::WriteFile(PHMHANDLEDATA pHMHandleData,
597 LPCVOID lpBuffer,
598 DWORD nNumberOfBytesToWrite,
599 LPDWORD lpNumberOfBytesWritten,
600 LPOVERLAPPED lpOverlapped,
601 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
602{
603 LPVOID lpRealBuf;
604 Win32MemMap *map;
605 DWORD offset, byteswritten;
606 BOOL bRC;
607
608 dprintfl(("KERNEL32: HMDeviceFileClass::WriteFile %s(%08x,%08x,%08x,%08x,%08x) - stub?\n",
609 lpHMDeviceName,
610 pHMHandleData,
611 lpBuffer,
612 nNumberOfBytesToWrite,
613 lpNumberOfBytesWritten,
614 lpOverlapped));
615
616 //SvL: It's legal for this pointer to be NULL
617 if(lpNumberOfBytesWritten)
618 *lpNumberOfBytesWritten = 0;
619 else
620 lpNumberOfBytesWritten = &byteswritten;
621
622 if((pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpOverlapped) {
623 dprintf(("FILE_FLAG_OVERLAPPED flag set, but lpOverlapped NULL!!"));
624 SetLastError(ERROR_INVALID_PARAMETER);
625 return FALSE;
626 }
627 if(!(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && lpOverlapped) {
628 dprintf(("Warning: lpOverlapped != NULL & !FILE_FLAG_OVERLAPPED; sync operation"));
629 }
630
631 //SvL: DosWrite doesn't like reading from memory addresses returned by
632 // DosAliasMem -> search for original memory mapped pointer and use
633 // that one + commit pages if not already present
634 map = Win32MemMapView::findMapByView((ULONG)lpBuffer, &offset, MEMMAP_ACCESS_READ);
635 if(map) {
636 lpRealBuf = (LPVOID)((ULONG)map->getMappingAddr() + offset);
637 DWORD nrpages = nNumberOfBytesToWrite/4096;
638 if((nNumberOfBytesToWrite+offset) & 0xfff)
639 nrpages++;
640
641 map->commitRange((ULONG)lpBuffer, offset & ~0xfff, FALSE, nrpages);
642 map->Release();
643 }
644 else lpRealBuf = (LPVOID)lpBuffer;
645
646 //If this file is also used in a memory map somewhere, then we need
647 //to tell the map to flush all modified contents to disk right NOW
648 DWORD curfilepos;
649 map = Win32MemMap::findMapByFile(pHMHandleData->hWin32Handle);
650 if(map && map->getFileHandle() != pHMHandleData->hWin32Handle) {
651 curfilepos = SetFilePointer(pHMHandleData, 0, NULL, FILE_CURRENT);
652
653 dprintf(("Flush memory maps to disk before writing!!"));
654 map->flushView(MMAP_FLUSHVIEW_ALL, curfilepos, nNumberOfBytesToWrite);
655 }
656
657 if(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) {
658 dprintf(("ERROR: Overlapped IO not yet implememented!!"));
659 }
660// else {
661 bRC = OSLibDosWrite(pHMHandleData->hHMHandle,
662 (PVOID)lpRealBuf,
663 nNumberOfBytesToWrite,
664 lpNumberOfBytesWritten);
665// }
666
667 if(map && bRC) {
668 dprintf(("Invalidate memory map after file writing!!"));
669 map->invalidatePages(curfilepos, *lpNumberOfBytesWritten);
670 }
671
672 dprintf(("KERNEL32: HMDeviceFileClass::WriteFile returned %08xh\n",
673 bRC));
674
675 return bRC;
676}
677
678
679/*****************************************************************************
680 * Name : DWORD HMDeviceFileClass::GetFileType
681 * Purpose : determine the handle type
682 * Parameters: PHMHANDLEDATA pHMHandleData
683 * Variables :
684 * Result : API returncode
685 * Remark :
686 * Status :
687 *
688 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
689 *****************************************************************************/
690
691DWORD HMDeviceFileClass::GetFileType(PHMHANDLEDATA pHMHandleData)
692{
693 dprintfl(("KERNEL32: HMDeviceFileClass::GetFileType %s(%08x)\n",
694 lpHMDeviceName,
695 pHMHandleData));
696
697 return FILE_TYPE_DISK;
698}
699
700
701/*****************************************************************************
702 * Name : DWORD HMDeviceFileClass::GetFileInformationByHandle
703 * Purpose : determine the handle type
704 * Parameters: PHMHANDLEDATA pHMHandleData
705 * BY_HANDLE_FILE_INFORMATION* pHFI
706 * Variables :
707 * Result : API returncode
708 * Remark :
709 * Status :
710 *
711 * Author : Patrick Haller [Wed, 1999/06/17 20:44]
712 *****************************************************************************/
713
714DWORD HMDeviceFileClass::GetFileInformationByHandle(PHMHANDLEDATA pHMHandleData,
715 BY_HANDLE_FILE_INFORMATION* pHFI)
716{
717 dprintfl(("KERNEL32: HMDeviceFileClass::GetFileInformationByHandle %s(%08xh,%08xh)\n",
718 lpHMDeviceName, pHMHandleData, pHFI));
719
720 HMFileInfo *fileInfo = (HMFileInfo *)pHMHandleData->dwUserData;
721 if(OSLibDosGetFileInformationByHandle(fileInfo->lpszFileName,
722 pHMHandleData->hHMHandle,
723 pHFI))
724 {
725 return TRUE;
726 }
727 dprintf(("GetFileInformationByHandle failed with error %d", GetLastError()));
728 return FALSE;
729
730}
731
732
733/*****************************************************************************
734 * Name : BOOL HMDeviceFileClass::SetEndOfFile
735 * Purpose : set end of file marker
736 * Parameters: PHMHANDLEDATA pHMHandleData
737 * Variables :
738 * Result : API returncode
739 * Remark :
740 * Status :
741 *
742 * Author : Patrick Haller [Wed, 1999/06/17 20:44]
743 *****************************************************************************/
744
745BOOL HMDeviceFileClass::SetEndOfFile(PHMHANDLEDATA pHMHandleData)
746{
747 dprintfl(("KERNEL32: HMDeviceFileClass::SetEndOfFile %s(%08xh)\n",
748 lpHMDeviceName,
749 pHMHandleData));
750
751 if(OSLibDosSetEndOfFile(pHMHandleData->hHMHandle)) {
752 return TRUE;
753 }
754 dprintf(("SetEndOfFile failed with error %d", GetLastError()));
755 return FALSE;
756}
757
758//******************************************************************************
759/*****************************************************************************
760 * Name : BOOL HMDeviceFileClass::SetFileTime
761 * Purpose : set file time
762 * Parameters: PHMHANDLEDATA pHMHandleData
763 * PFILETIME pFT1
764 * PFILETIME pFT2
765 * PFILETIME pFT3
766 * Variables :
767 * Result : API returncode
768 * Remark :
769 * Status :
770 *
771 * Author : Patrick Haller [Wed, 1999/06/17 20:44] mod. DT
772 *****************************************************************************/
773
774BOOL HMDeviceFileClass::SetFileTime(PHMHANDLEDATA pHMHandleData,
775 LPFILETIME pFT1,
776 LPFILETIME pFT2,
777 LPFILETIME pFT3)
778{
779 dprintfl(("KERNEL32: HMDeviceFileClass::SetFileTime %s(%08xh,%08xh,%08xh,%08xh)\n",
780 lpHMDeviceName, pHMHandleData, pFT1, pFT2, pFT3));
781
782 if(OSLibDosSetFileTime(pHMHandleData->hHMHandle, pFT1, pFT2, pFT3)) return TRUE;
783
784 dprintf(("SetFileTime failed with error %d", GetLastError()));
785 return FALSE;
786}
787
788/*****************************************************************************
789 * Name : BOOL HMDeviceFileClass::GetFileTime
790 * Purpose : get file time
791 * Parameters: PHMHANDLEDATA pHMHandleData
792 * PFILETIME pFT1
793 * PFILETIME pFT2
794 * PFILETIME pFT3
795 * Variables :
796 * Result : API returncode
797 * Remark :
798 * Status :
799 *
800 * Author : SvL mod. DT
801 *****************************************************************************/
802
803BOOL HMDeviceFileClass::GetFileTime(PHMHANDLEDATA pHMHandleData,
804 LPFILETIME pFT1,
805 LPFILETIME pFT2,
806 LPFILETIME pFT3)
807{
808 if(!pFT1 && !pFT2 && !pFT3) {//TODO: does NT do this?
809 dprintf(("ERROR: GetFileTime: invalid parameter!"));
810 SetLastError(ERROR_INVALID_PARAMETER);
811 return FALSE;
812 }
813
814 if(OSLibDosGetFileTime(pHMHandleData->hHMHandle, pFT1, pFT2, pFT3)) return TRUE;
815 dprintf(("GetFileTime failed with error %d", GetLastError()));
816 return FALSE;
817}
818
819/*****************************************************************************
820 * Name : DWORD HMDeviceFileClass::GetFileSize
821 * Purpose : set file time
822 * Parameters: PHMHANDLEDATA pHMHandleData
823 * PDWORD pSize
824 * Variables :
825 * Result : API returncode
826 * Remark :
827 * Status :
828 *
829 * Author : Patrick Haller [Wed, 1999/06/17 20:44]
830 *****************************************************************************/
831
832DWORD HMDeviceFileClass::GetFileSize(PHMHANDLEDATA pHMHandleData,
833 PDWORD lpdwFileSizeHigh)
834{
835 dprintfl(("KERNEL32: HMDeviceFileClass::GetFileSize %s(%08xh,%08xh)\n",
836 lpHMDeviceName,
837 pHMHandleData,
838 lpdwFileSizeHigh));
839
840 if(lpdwFileSizeHigh)
841 *lpdwFileSizeHigh = 0;
842
843 return OSLibDosGetFileSize(pHMHandleData->hHMHandle, lpdwFileSizeHigh);
844}
845
846/*****************************************************************************
847 * Name : DWORD HMDeviceFileClass::SetFilePointer
848 * Purpose : set file pointer
849 * Parameters: PHMHANDLEDATA pHMHandleData
850 * LONG lDistanceToMove
851 * PLONG lpDistanceToMoveHigh
852 * DWORD dwMoveMethod
853 * Variables :
854 * Result : API returncode
855 * Remark :
856 * Status :
857 *
858 * Author : Patrick Haller [Wed, 1999/06/17 20:44]
859 *****************************************************************************/
860
861DWORD HMDeviceFileClass::SetFilePointer(PHMHANDLEDATA pHMHandleData,
862 LONG lDistanceToMove,
863 PLONG lpDistanceToMoveHigh,
864 DWORD dwMoveMethod)
865{
866 DWORD ret;
867 HMFileInfo *fileInfo = (HMFileInfo *)pHMHandleData->dwUserData;
868
869 dprintfl(("KERNEL32: HMDeviceFileClass::SetFilePointer %s(%08xh,%08xh,%08xh,%08xh)\n",
870 lpHMDeviceName,
871 pHMHandleData,
872 lDistanceToMove,
873 lpDistanceToMoveHigh,
874 dwMoveMethod));
875
876 if(fileInfo && fileInfo->dwLXOffset)
877 {
878 switch(dwMoveMethod)
879 {
880 case FILE_BEGIN:
881 dprintf(("SetFilePointer FILE_BEGIN (LX) -> change offset from %x to %x", lDistanceToMove, lDistanceToMove+fileInfo->dwLXOffset));
882 lDistanceToMove += fileInfo->dwLXOffset;
883 break;
884
885 case FILE_END:
886 //Could overshoot the virtual beginning of the PE file
887 lDistanceToMove -= MAGIC_STUBEXE_SIZE;
888 dprintf(("SetFilePointer FILE_END -> might be dangerous!!"));
889 break;
890
891 }
892 }
893
894 ret = OSLibDosSetFilePointer(pHMHandleData->hHMHandle,
895 lDistanceToMove,
896 (DWORD *)lpDistanceToMoveHigh,
897 dwMoveMethod);
898
899 if(ret == -1) {
900 dprintf(("SetFilePointer failed (error = %d)", GetLastError()));
901 }
902 return ret;
903}
904
905
906/*****************************************************************************
907 * Name : BOOL HMDeviceFileClass::LockFile
908 * Purpose : file locking
909 * Parameters: PHMHANDLEDATA pHMHandleData
910 * DWORD arg2
911 * DWORD arg3
912 * DWORD arg4
913 * DWORD arg5
914 * Variables :
915 * Result : API returncode
916 * Remark :
917 * Status :
918 *
919 * Author : Patrick Haller [Wed, 1999/06/17 20:44]
920 *****************************************************************************/
921
922BOOL HMDeviceFileClass::LockFile(PHMHANDLEDATA pHMHandleData,
923 DWORD dwFileOffsetLow,
924 DWORD dwFileOffsetHigh,
925 DWORD cbLockLow,
926 DWORD cbLockHigh)
927{
928 dprintfl(("KERNEL32: HMDeviceFileClass::LockFile %s(%08xh,%08xh,%08xh,%08xh,%08xh)\n",
929 lpHMDeviceName,
930 pHMHandleData,
931 dwFileOffsetLow,
932 dwFileOffsetHigh,
933 cbLockLow,
934 cbLockHigh));
935
936 return OSLibDosLockFile(pHMHandleData->hHMHandle,
937 LOCKFILE_EXCLUSIVE_LOCK,
938 dwFileOffsetLow,
939 dwFileOffsetHigh,
940 cbLockLow,
941 cbLockHigh,
942 NULL);
943}
944
945/*****************************************************************************
946 * Name : DWORD HMDeviceFileClass::LockFileEx
947 * Purpose : file locking
948 * Parameters: PHMHANDLEDATA pHMHandleData
949 * DWORD dwFlags
950 * DWORD dwReserved
951 * DWORD nNumberOfBytesToLockLow
952 * DWORD nNumberOfBytesToLockHigh
953 * LPOVERLAPPED lpOverlapped
954 * Variables :
955 * Result : API returncode
956 * Remark :
957 * Status :
958 *
959 * Author : Patrick Haller [Wed, 1999/06/17 20:44]
960 *****************************************************************************/
961
962BOOL HMDeviceFileClass::LockFileEx(PHMHANDLEDATA pHMHandleData,
963 DWORD dwFlags,
964 DWORD dwReserved,
965 DWORD nNumberOfBytesToLockLow,
966 DWORD nNumberOfBytesToLockHigh,
967 LPOVERLAPPED lpOverlapped)
968{
969
970 dprintfl(("KERNEL32: HMDeviceFileClass::LockFileEx %s(%08xh,%08xh,%08xh,%08xh,%08xh,%08xh) not completely implemented!",
971 lpHMDeviceName,
972 pHMHandleData,
973 dwFlags,
974 dwReserved,
975 nNumberOfBytesToLockLow,
976 nNumberOfBytesToLockHigh,
977 lpOverlapped));
978
979
980 return(OSLibDosLockFile(pHMHandleData->hHMHandle,
981 dwFlags,
982 lpOverlapped->Offset,
983 lpOverlapped->OffsetHigh,
984 nNumberOfBytesToLockLow,
985 nNumberOfBytesToLockHigh,
986 lpOverlapped));
987}
988
989
990/*****************************************************************************
991 * Name : DWORD HMDeviceFileClass::UnlockFile
992 * Purpose : file locking
993 * Parameters: PHMHANDLEDATA pHMHandleData
994 * DWORD arg2
995 * DWORD arg3
996 * DWORD arg4
997 * DWORD arg5
998 * Variables :
999 * Result : API returncode
1000 * Remark :
1001 * Status :
1002 *
1003 * Author : Patrick Haller [Wed, 1999/06/17 20:44]
1004 *****************************************************************************/
1005
1006BOOL HMDeviceFileClass::UnlockFile(PHMHANDLEDATA pHMHandleData,
1007 DWORD dwFileOffsetLow,
1008 DWORD dwFileOffsetHigh,
1009 DWORD cbLockLow,
1010 DWORD cbLockHigh)
1011{
1012 dprintfl(("KERNEL32: HMDeviceFileClass::UnlockFile %s(%08xh,%08xh,%08xh,%08xh,%08xh)\n",
1013 lpHMDeviceName,
1014 pHMHandleData,
1015 dwFileOffsetLow,
1016 dwFileOffsetHigh,
1017 cbLockLow,
1018 cbLockHigh));
1019
1020 return OSLibDosUnlockFile(pHMHandleData->hHMHandle,
1021 dwFileOffsetLow,
1022 dwFileOffsetHigh,
1023 cbLockLow,
1024 cbLockHigh,
1025 NULL);
1026}
1027
1028
1029
1030/*****************************************************************************
1031 * Name : DWORD HMDeviceFileClass::UnlockFileEx
1032 * Purpose : file locking
1033 * Parameters: PHMHANDLEDATA pHMHandleData
1034 * DWORD dwFlags
1035 * DWORD dwReserved
1036 * DWORD nNumberOfBytesToLockLow
1037 * DWORD nNumberOfBytesToLockHigh
1038 * LPOVERLAPPED lpOverlapped
1039 * Variables :
1040 * Result : API returncode
1041 * Remark :
1042 * Status :
1043 *
1044 * Author : Patrick Haller [Wed, 1999/06/17 20:44]
1045 *****************************************************************************/
1046
1047BOOL HMDeviceFileClass::UnlockFileEx(PHMHANDLEDATA pHMHandleData,
1048 DWORD dwReserved,
1049 DWORD nNumberOfBytesToLockLow,
1050 DWORD nNumberOfBytesToLockHigh,
1051 LPOVERLAPPED lpOverlapped)
1052{
1053
1054 dprintfl(("KERNEL32: HMDeviceFileClass::UnlockFileEx %s(%08xh,%08xh,%08xh,%08xh,%08xh) not completely implemented!",
1055 lpHMDeviceName,
1056 pHMHandleData,
1057 dwReserved,
1058 nNumberOfBytesToLockLow,
1059 nNumberOfBytesToLockHigh,
1060 lpOverlapped));
1061
1062
1063 return(OSLibDosUnlockFile(pHMHandleData->hHMHandle,
1064 lpOverlapped->Offset,
1065 lpOverlapped->OffsetHigh,
1066 nNumberOfBytesToLockLow,
1067 nNumberOfBytesToLockHigh,
1068 lpOverlapped));
1069}
1070
1071
1072/*****************************************************************************
1073 * Name : DWORD HMDeviceFileClass::FlushFileBuffers
1074 * Purpose : flush the buffers of a file
1075 * Parameters: PHMHANDLEDATA pHMHandleData
1076 * Variables :
1077 * Result : API returncode
1078 * Remark :
1079 * Status :
1080 *
1081 * Author : Patrick Haller [Wed, 1999/06/17 20:44]
1082 *****************************************************************************/
1083
1084BOOL HMDeviceFileClass::FlushFileBuffers(PHMHANDLEDATA pHMHandleData)
1085{
1086 dprintfl(("KERNEL32: HMDeviceFileClass:FlushFileBuffers(%08xh)\n",
1087 pHMHandleData->hHMHandle));
1088
1089 return(OSLibDosFlushFileBuffers(pHMHandleData->hHMHandle));
1090}
1091
1092
1093/*****************************************************************************
1094 * Name : DWORD HMDeviceFileClass::GetOverlappedResult
1095 * Purpose : asynchronus I/O
1096 * Parameters: PHMHANDLEDATA pHMHandleData
1097 * LPOVERLAPPED arg2
1098 * LPDWORD arg3
1099 * BOOL arg4
1100 * Variables :
1101 * Result : API returncode
1102 * Remark :
1103 * Status :
1104 *
1105 * Author : Patrick Haller [Wed, 1999/06/17 20:44]
1106 *****************************************************************************/
1107
1108BOOL HMDeviceFileClass::GetOverlappedResult(PHMHANDLEDATA pHMHandleData,
1109 LPOVERLAPPED arg2,
1110 LPDWORD arg3,
1111 BOOL arg4)
1112{
1113 dprintfl(("KERNEL32-WARNING: HMDeviceFileClass::GetOverlappedResult(%08xh,%08xh,%08xh,%08xh) STUB!!",
1114 pHMHandleData->hHMHandle,
1115 arg2,
1116 arg3,
1117 arg4));
1118
1119 return FALSE;
1120// return(O32_GetOverlappedResult(pHMHandleData->hHMHandle,
1121// arg2,
1122// arg3,
1123// arg4));
1124}
1125/******************************************************************************
1126 * Name : DWORD HMDeviceFileClass::GetFileNameFromHandle
1127 * Purpose : the name of the file associated with the system handle (if any)
1128 * Parameters: PHMHANDLEDATA pHMHandleData
1129 * Variables :
1130 * Result : BOOLEAN
1131 * Remark :
1132 * Status :
1133 *
1134 * Author : SvL
1135 ******************************************************************************/
1136BOOL HMDeviceFileClass::GetFileNameFromHandle(PHMHANDLEDATA pHMHandleData,
1137 LPSTR lpszFileName, DWORD cbFileName)
1138{
1139 HMFileInfo *fileInfo = (HMFileInfo *)pHMHandleData->dwUserData;
1140
1141 if(fileInfo == NULL || strlen(fileInfo->lpszFileName) >= cbFileName) {
1142 if(fileInfo) DebugInt3();
1143 return FALSE;
1144 }
1145 strcpy(lpszFileName, fileInfo->lpszFileName);
1146
1147 return TRUE;
1148}
1149
1150//******************************************************************************
1151//******************************************************************************
1152// File information handle class
1153//
1154// When the application opens a file with CreateFile and 0 for desired access,
1155// then we need to create a handle with limited access.
1156//
1157// MSDN:
1158//
1159// If this parameter is zero, the application can query file and device attributes
1160// without accessing the device. This is useful if an application wants to determine
1161// the size of a floppy disk drive and the formats it supports without requiring
1162// a floppy in the drive. It can also be used to test for the file's or directory's
1163// existence without opening it for read or write access.
1164//
1165//******************************************************************************
1166//******************************************************************************
1167
1168/******************************************************************************
1169 * Name : DWORD HMDeviceInfoFileClass::CreateFile
1170 * Purpose : this is called from the handle manager if a CreateFile() is
1171 * performed on a handle
1172 * Parameters: LPCSTR lpFileName name of the file / device
1173 * PHMHANDLEDATA pHMHandleData data of the NEW handle
1174 * PVOID lpSecurityAttributes ignored
1175 * PHMHANDLEDATA pHMHandleDataTemplate data of the template handle
1176 * Variables :
1177 * Result :
1178 * Remark :
1179 * Status : NO_ERROR - API succeeded
1180 * other - what is to be set in SetLastError
1181 *
1182 * Author : SvL
1183 *****************************************************************************/
1184DWORD HMDeviceInfoFileClass::CreateFile (LPCSTR lpFileName,
1185 PHMHANDLEDATA pHMHandleData,
1186 PVOID lpSecurityAttributes,
1187 PHMHANDLEDATA pHMHandleDataTemplate)
1188{
1189 char filepath[260];
1190 DWORD dwAttr;
1191
1192 dprintfl(("KERNEL32: HMDeviceInfoFileClass::CreateFile %s(%s,%08x,%08x,%08x)\n",
1193 lpHMDeviceName,
1194 lpFileName,
1195 pHMHandleData,
1196 lpSecurityAttributes,
1197 pHMHandleDataTemplate));
1198
1199 ParsePath(lpFileName, filepath, sizeof(filepath));
1200
1201 //convert to long file name if in 8.3 hashed format
1202 GetLongPathNameA(filepath, filepath, sizeof(filepath));
1203 lpFileName = filepath;
1204
1205
1206 dwAttr = GetFileAttributesA(lpFileName);
1207 if(dwAttr == -1) {
1208 return GetLastError();
1209 }
1210
1211 pHMHandleData->dwUserData = (DWORD) new HMFileInfo(0, (LPSTR)lpFileName, lpSecurityAttributes);
1212 pHMHandleData->hHMHandle = 0x8000000;
1213 return (NO_ERROR);
1214
1215}
1216/******************************************************************************
1217 * Name : BOOL HMDeviceFileClass::CloseHandle
1218 * Purpose : close the handle
1219 * Parameters: PHMHANDLEDATA pHMHandleData
1220 * Variables :
1221 * Result : API returncode
1222 * Remark :
1223 * Status :
1224 *
1225 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
1226 *****************************************************************************/
1227BOOL HMDeviceInfoFileClass::CloseHandle(PHMHANDLEDATA pHMHandleData)
1228{
1229 HMFileInfo *fileInfo = (HMFileInfo *)pHMHandleData->dwUserData;
1230
1231 dprintfl(("KERNEL32: HMDeviceInfoFileClass::CloseHandle(%08x)\n",
1232 pHMHandleData->hHMHandle));
1233
1234 if(fileInfo) {
1235 delete fileInfo;
1236 }
1237 return TRUE;
1238}
1239/******************************************************************************
1240 * Name : BOOL HMDeviceInfoFileClass::GetFileTime
1241 * Purpose : Get file time
1242 * Parameters: PHMHANDLEDATA pHMHandleData
1243 * PFILETIME pFT1
1244 * PFILETIME pFT2
1245 * PFILETIME pFT3
1246 * Variables :
1247 * Result : API returncode
1248 * Remark :
1249 * Status :
1250 *
1251 * Author : SvL
1252 *****************************************************************************/
1253BOOL HMDeviceInfoFileClass::GetFileTime (PHMHANDLEDATA pHMHandleData,
1254 LPFILETIME pFT1,
1255 LPFILETIME pFT2,
1256 LPFILETIME pFT3)
1257{
1258 HMFileInfo *fileInfo = (HMFileInfo *)pHMHandleData->dwUserData;
1259
1260 if(!pFT1 && !pFT2 && !pFT3) {//TODO: does NT do this?
1261 dprintf(("ERROR: GetFileTime: invalid parameter!"));
1262 SetLastError(ERROR_INVALID_PARAMETER);
1263 return FALSE;
1264 }
1265 WIN32_FIND_DATAA finddata;
1266 HANDLE hFind;
1267
1268 hFind = FindFirstFileA(fileInfo->lpszFileName, &finddata);
1269 if(hFind == INVALID_HANDLE_VALUE) {
1270 return GetLastError();
1271 }
1272 if(pFT1) {
1273 *pFT1 = finddata.ftCreationTime;
1274 }
1275 if(pFT2) {
1276 *pFT2 = finddata.ftLastAccessTime;
1277 }
1278 if(pFT3) {
1279 *pFT3 = finddata.ftLastWriteTime;
1280 }
1281 FindClose(hFind);
1282 SetLastError(ERROR_SUCCESS);
1283 return TRUE;
1284}
1285/******************************************************************************
1286 * Name : DWORD HMDeviceInfoFileClass::GetFileSize
1287 * Purpose : get file size
1288 * Parameters: PHMHANDLEDATA pHMHandleData
1289 * PDWORD pSize
1290 * Variables :
1291 * Result : API returncode
1292 * Remark : Doesn't fail for directories; just returns 0 (verified in NT4, SP6)
1293 * Status :
1294 *
1295 * Author : SvL
1296 *****************************************************************************/
1297DWORD HMDeviceInfoFileClass::GetFileSize(PHMHANDLEDATA pHMHandleData,
1298 PDWORD lpdwFileSizeHigh)
1299{
1300 HMFileInfo *fileInfo = (HMFileInfo *)pHMHandleData->dwUserData;
1301
1302 SetLastError(ERROR_SUCCESS);
1303
1304 if(lpdwFileSizeHigh)
1305 *lpdwFileSizeHigh = 0;
1306
1307 if(fileInfo == NULL) {
1308 DebugInt3();
1309 SetLastError(ERROR_INVALID_PARAMETER); //TODO
1310 return -1; //INVALID_FILE_SIZE;
1311 }
1312
1313 WIN32_FIND_DATAA finddata;
1314 HANDLE hFind;
1315
1316 hFind = FindFirstFileA(fileInfo->lpszFileName, &finddata);
1317 if(hFind == INVALID_HANDLE_VALUE) {
1318 return GetLastError();
1319 }
1320 if(lpdwFileSizeHigh) {
1321 *lpdwFileSizeHigh = finddata.nFileSizeHigh;
1322 }
1323 FindClose(hFind);
1324
1325 if(fileInfo->dwLXOffset)
1326 {
1327 //subtract the LX header and magic qword from the file size
1328 dprintf(("GetFileSize (LX) -> change size from %x to %x", finddata.nFileSizeLow, finddata.nFileSizeLow-fileInfo->dwLXOffset-MAGIC_STUBEXE_SIZE));
1329 finddata.nFileSizeLow -= (fileInfo->dwLXOffset+MAGIC_STUBEXE_SIZE);
1330 }
1331 return finddata.nFileSizeLow;
1332}
1333/******************************************************************************
1334 * Name : DWORD HMDeviceFileClass::GetFileNameFromHandle
1335 * Purpose : the name of the file associated with the system handle (if any)
1336 * Parameters: PHMHANDLEDATA pHMHandleData
1337 * Variables :
1338 * Result : BOOLEAN
1339 * Remark :
1340 * Status :
1341 *
1342 * Author : SvL
1343 ******************************************************************************/
1344BOOL HMDeviceInfoFileClass::GetFileNameFromHandle(PHMHANDLEDATA pHMHandleData,
1345 LPSTR lpszFileName, DWORD cbFileName)
1346{
1347 HMFileInfo *fileInfo = (HMFileInfo *)pHMHandleData->dwUserData;
1348
1349 if(fileInfo == NULL || strlen(fileInfo->lpszFileName) >= cbFileName) {
1350 if(fileInfo) DebugInt3();
1351 return FALSE;
1352 }
1353 strcpy(lpszFileName, fileInfo->lpszFileName);
1354
1355 return TRUE;
1356}
1357/******************************************************************************
1358 * Name : DWORD HMDeviceFileClass::GetFileType
1359 * Purpose : determine the handle type
1360 * Parameters: PHMHANDLEDATA pHMHandleData
1361 * Variables :
1362 * Result : API returncode
1363 * Remark : Returns FILE_TYPE_DISK for both files and directories
1364 * Status :
1365 *
1366 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
1367 ******************************************************************************/
1368DWORD HMDeviceInfoFileClass::GetFileType(PHMHANDLEDATA pHMHandleData)
1369{
1370 dprintfl(("KERNEL32: HMDeviceInfoFileClass::GetFileType %s(%08x)\n",
1371 lpHMDeviceName,
1372 pHMHandleData));
1373
1374 return FILE_TYPE_DISK;
1375}
1376//******************************************************************************
1377//******************************************************************************
1378HMFileInfo::HMFileInfo(HANDLE hFile, LPSTR lpszFileName, PVOID lpSecurityAttributes)
1379{
1380 // get the full path (this is necessary in particular for GetFileInformationByHandle)
1381 char fullPath[260];
1382 if (!OSLibDosQueryPathInfo(lpszFileName, FIL_QUERYFULLNAME, fullPath, sizeof(fullPath))) {
1383 lpszFileName = fullPath;
1384 }
1385
1386 this->lpszFileName = (LPSTR)malloc(strlen(lpszFileName)+1);
1387 if(!this->lpszFileName) {
1388 DebugInt3();
1389 }
1390 strcpy(this->lpszFileName, lpszFileName);
1391 this->lpSecurityAttributes = lpSecurityAttributes;
1392 dwLXOffset = 0;
1393
1394 //Only check files that end with .exe for now; they might be prepended with
1395 //an LX header. We need to skip that to present the original file to the
1396 //caller
1397 if(hFile && !stricmp(lpszFileName + strlen(lpszFileName) - 4, ".EXE"))
1398 {
1399 ULONG action, ulRead, signature, ulFileSize;
1400 ULONG magic[2];
1401 IMAGE_DOS_HEADER doshdr;
1402
1403 //read dos header
1404 if(!OSLibDosRead(hFile, (LPVOID)&doshdr, sizeof(doshdr), &ulRead)) {
1405 goto failure;
1406 }
1407 if(OSLibDosSetFilePointer(hFile, doshdr.e_lfanew, NULL, FILE_BEGIN) != doshdr.e_lfanew) {
1408 goto failure;
1409 }
1410 //read signature dword
1411 if(!OSLibDosRead(hFile, (LPVOID)&signature, sizeof(signature), &ulRead)) {
1412 goto failure;
1413 }
1414
1415 //Make sure it's an LX executable before continueing
1416 if(doshdr.e_magic != IMAGE_DOS_SIGNATURE || (WORD)signature != IMAGE_OS2_SIGNATURE_LX)
1417 {
1418 goto failure;
1419 }
1420
1421 //magic signature located at 8 bytes from file end
1422 if(OSLibDosSetFilePointer(hFile, -8, NULL, FILE_END) == -1) {
1423 goto failure;
1424 }
1425 //read magic signature + pe offset
1426 if(!OSLibDosRead(hFile, (LPVOID)&magic[0], sizeof(magic), &ulRead)) {
1427 goto failure;
1428 }
1429 if(magic[0] != MAGIC_STUBEXE_SIGNATURE || magic[1] > ulFileSize) {
1430 goto failure;
1431 }
1432 //this is the offset of the PE image inside our LX executable
1433 dwLXOffset = magic[1];
1434
1435 dprintf(("LX wrapper: PE file %s starts at %x", lpszFileName, dwLXOffset));
1436 //reset file pointer to PE image start
1437 if(OSLibDosSetFilePointer(hFile, dwLXOffset, NULL, FILE_BEGIN) != dwLXOffset) {
1438 DebugInt3();
1439 }
1440 goto end;
1441
1442failure:
1443 //reset file pointer to file start
1444 if(OSLibDosSetFilePointer(hFile, 0, NULL, FILE_BEGIN) != 0) {
1445 DebugInt3();
1446 }
1447 }
1448end:
1449 return;
1450}
1451//******************************************************************************
1452//******************************************************************************
1453HMFileInfo::~HMFileInfo()
1454{
1455 if(lpszFileName) {
1456 free(lpszFileName);
1457 lpszFileName = NULL;
1458 }
1459}
1460
1461//*****************************************************************************
1462//Parses and copies path
1463//OpenFile in NT4, SP6 accepts double (or more) backslashes as separators for directories!
1464//(OS/2 doesn't)
1465//Girotel 2.0 (Dutch banking app) seems to depend on this behaviour
1466//*****************************************************************************
1467static void ParsePath(LPCSTR lpszFileName, LPSTR lpszParsedFileName, DWORD length)
1468{
1469 int i=0;
1470
1471 while(*lpszFileName != 0 && i < length-1) {
1472 *lpszParsedFileName++ = *lpszFileName;
1473 if(*lpszFileName == '\\') {
1474 while(*lpszFileName == '\\') {
1475 lpszFileName++;
1476 }
1477 }
1478 else {
1479 lpszFileName++;
1480 }
1481 i++;
1482 }
1483 *lpszParsedFileName = 0;
1484}
1485//******************************************************************************
1486//******************************************************************************
Note: See TracBrowser for help on using the repository browser.