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

Last change on this file since 22024 was 22024, checked in by dmik, 13 years ago

kernel32: Fix inverted return values in dummy HMDeviceHandler implementations.

This in particular affected GetFileInformationByHandle and other APIs. Some applications
(like Flash 10.1+) could be completely confused by the fact that the unimplemented API
returns success.

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