source: trunk/src/kernel32/hmfile.cpp

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

kernel32: Fix Win32ImageBase::matchModName().

As opposed to the declared functionality, it was comparing the name part
of the argument with the full path of the stored module name and this would
obviously not work if the module name were a full path.

One of the failig cases was a frequent attempt to retrieve the resources of the
current executable by doing LoadLibraryEx() with the full executable name.

File size: 51.6 KB
RevLine 
[10564]1/* $Id: hmfile.cpp,v 1.46 2004-04-02 15:14:54 sandervl Exp $ */
[3642]2
3/*
4 * File IO win32 apis
5 *
6 * Copyright 1999-2000 Sander van Leeuwen
7 *
[3948]8 *
[3642]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"
[21302]37#include <customloader.h>
[3642]38
[4682]39#define DBG_LOCALLOG DBG_hmfile
[3642]40#include "dbglocal.h"
41
[10064]42static void ParsePath(LPCSTR lpszFileName, LPSTR lpszParsedFileName, DWORD length);
43
[21564]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
[3642]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 :
[21564]67 * Remark :
[3642]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
[7549]74DWORD HMDeviceFileClass::CreateFile (LPCSTR lpFileName,
[3642]75 PHMHANDLEDATA pHMHandleData,
76 PVOID lpSecurityAttributes,
77 PHMHANDLEDATA pHMHandleDataTemplate)
78{
79 HFILE hFile;
80 HFILE hTemplate;
[4683]81 char filepath[260];
[3642]82
83 dprintfl(("KERNEL32: HMDeviceFileClass::CreateFile %s(%s,%08x,%08x,%08x)\n",
84 lpHMDeviceName,
85 lpFileName,
86 pHMHandleData,
87 lpSecurityAttributes,
88 pHMHandleDataTemplate));
[21564]89
[7474]90 ParsePath(lpFileName, filepath, sizeof(filepath));
[9453]91
92 //convert to long file name if in 8.3 hashed format
93 GetLongPathNameA(filepath, filepath, sizeof(filepath));
[7474]94 lpFileName = filepath;
[3642]95
96 // create from template
97 if (pHMHandleDataTemplate != NULL)
98 hTemplate = pHMHandleDataTemplate->hHMHandle;
99 else
100 hTemplate = 0;
101
[3999]102 //TODO: FILE_SHARE_DELETE
[3642]103 hFile = OSLibDosCreateFile((LPSTR)lpFileName,
104 pHMHandleData->dwAccess,
105 pHMHandleData->dwShare,
106 (LPSECURITY_ATTRIBUTES)lpSecurityAttributes,
107 pHMHandleData->dwCreation,
108 pHMHandleData->dwFlags,
109 hTemplate);
[3995]110
[3642]111 if (hFile != INVALID_HANDLE_ERROR)
112 {
[21302]113 pHMHandleData->dwUserData = (DWORD) new HMFileInfo(hFile, (LPSTR)lpFileName, lpSecurityAttributes);
[4682]114 pHMHandleData->hHMHandle = hFile;
115 return (NO_ERROR);
[3642]116 }
117 else {
[4682]118 dprintf(("CreateFile failed; error %d", GetLastError()));
119 return(GetLastError());
[3642]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
[9530]134 * UTC Time or Localtime ?
[21564]135 * GetFileTime is changed, Returns UTC-time yet !!!!!
[3642]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
[7549]142DWORD HMDeviceFileClass::OpenFile (LPCSTR lpszFileName,
[3642]143 PHMHANDLEDATA pHMHandleData,
144 OFSTRUCT *pOFStruct,
145 UINT fuMode)
146{
[5791]147 HFILE hFile;
148 FILETIME filetime;
149 WORD filedatetime[2];
150 char filepath[260];
151 LPSTR lpFileName = (LPSTR)lpszFileName;
[3642]152
[5791]153 SetLastError(ERROR_SUCCESS);
[3642]154
[5791]155 //Re-open using name in OFSTRUCT
156 if(fuMode & OF_REOPEN)
157 lpFileName = (LPSTR)pOFStruct->szPathName;
158 else memset(pOFStruct, 0, sizeof(OFSTRUCT));
[3642]159
[5791]160 dprintf(("KERNEL32: HMDeviceFileClass::OpenFile %s(%s,%08x,%08x,%08x)", lpHMDeviceName,
161 lpFileName, pHMHandleData, pOFStruct, fuMode));
[3642]162
[5791]163 if(lpFileName == NULL) {
164 dprintf(("Invalid name (NULL)!"));
165 SetLastError(ERROR_INVALID_NAME);
166 return HFILE_ERROR;
167 }
[5715]168
[5791]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;
[3642]179
[10071]180 if (SearchPathA(NULL, lpFileName, NULL, sizeof(filepath), filepath, &filenameinpath) == 0)
[3678]181 {
[10071]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));
[5791]196 }
197 lpFileName = filepath;
[4682]198 }
[5791]199 else {
[10071]200 #if 1 /* Canonicalize the path should be the right thing to do I think... */
201 GetFullPathNameA(lpFileName, sizeof(filepath), filepath, NULL);
[21564]202 #else
[5791]203 ParsePath(lpFileName, filepath, sizeof(filepath));
[10071]204 #endif
[9453]205
206 //convert to long file name if in 8.3 hashed format
207 GetLongPathNameA(filepath, filepath, sizeof(filepath));
[5791]208 lpFileName = filepath;
209 }
[4682]210
[5791]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;
[3642]216
[21564]217
218 /*
[10071]219 * Do the parse stuff now and do a quick exit.
[21564]220 * Based on testcase (5) and MSDN:
[10071]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
[21564]233
[5791]234 hFile = OSLibDosOpenFile((LPSTR)lpFileName, fuMode);
[21564]235
[5791]236 if(hFile != INVALID_HANDLE_ERROR)
237 {
[4682]238 //Needed for GetFileTime
239 pHMHandleData->hHMHandle = hFile;
240 GetFileTime(pHMHandleData,
[3642]241 NULL,
242 NULL,
243 &filetime );
[21564]244
245 /* UTC Time or Localtime ? GetFileTime Returns UTC-time yet ? !!!!! */
[4682]246 FileTimeToDosDateTime(&filetime,
[3642]247 &filedatetime[0],
248 &filedatetime[1] );
[4682]249 memcpy(pOFStruct->reserved, filedatetime, sizeof(pOFStruct->reserved));
[21564]250
[5791]251 if(fuMode & OF_DELETE)
252 {
[4682]253 OSLibDosClose(hFile);
254 OSLibDosDelete((LPSTR)lpFileName);
[5791]255 }
256 else
257 if(fuMode & OF_EXIST)
258 {
259 OSLibDosClose(hFile);
260 hFile = HFILE_ERROR;
261 }
[21564]262
[4682]263 if((fuMode & OF_VERIFY))
[10071]264 {//TODO: what's this?? we copy the time above...
[4682]265 if(memcmp(pOFStruct->reserved, filedatetime, sizeof(pOFStruct->reserved)))
266 {
[5791]267 OSLibDosClose(hFile);
268 SetLastError(ERROR_FILE_NOT_FOUND);
[4682]269 }
[5791]270 hFile = HFILE_ERROR;
[4682]271 }
[21564]272
[4682]273 pOFStruct->nErrCode = GetLastError();
274 pHMHandleData->hHMHandle = hFile;
[21564]275
[3642]276 if(hFile != HFILE_ERROR) {
[21302]277 pHMHandleData->dwUserData = (DWORD) new HMFileInfo(hFile, (LPSTR)lpFileName, NULL);
[5791]278 }
279 return (NO_ERROR);
[4682]280 }
[5791]281 else {
[4682]282 DWORD rc = GetLastError();
[21564]283
[4682]284 if(fuMode & OF_EXIST)
285 {
286 if(rc == ERROR_OPEN_FAILED) {
[5791]287 SetLastError(ERROR_FILE_NOT_FOUND);
288 }
[4682]289 }
[5791]290 //todo: OF_PROMPT handling (pop up message box)
[4682]291 }
[5791]292 // error branch
293 pOFStruct->nErrCode = GetLastError();
294 dprintf(("KERNEL32: HMDeviceFileClass::OpenFile Error %08xh\n",
295 pOFStruct->nErrCode));
[3642]296
[5791]297 // return != NO_ERROR => error code
298 return(hFile);
[3642]299}
300
301/*****************************************************************************
302 * Name : HMDeviceFileClass::DuplicateHandle
[4682]303 * Purpose :
304 * Parameters:
[3642]305 * various parameters as required
306 * Variables :
307 * Result :
308 * Remark : DUPLICATE_CLOSE_SOURCE flag handled in HMDuplicateHandle
[4682]309 *
[3642]310 * Status : partially implemented
311 *
312 * Author : SvL
313 *****************************************************************************/
[9748]314BOOL HMDeviceFileClass::DuplicateHandle(HANDLE srchandle, PHMHANDLEDATA pHMHandleData,
[3714]315 HANDLE srcprocess,
316 PHMHANDLEDATA pHMSrcHandle,
317 HANDLE destprocess,
318 DWORD fdwAccess,
319 BOOL fInherit,
[3948]320 DWORD fdwOptions,
321 DWORD fdwOdinOptions)
[3642]322{
323 HMFileInfo *srcfileinfo = (HMFileInfo *)pHMSrcHandle->dwUserData;
[3714]324 DWORD rc;
[3642]325
[21302]326 dprintf(("KERNEL32:HMDeviceFileClass::DuplicateHandle (%08x,%08x,%08x,%08x)",
[3642]327 pHMHandleData,
[4682]328 srcprocess,
329 pHMSrcHandle->hHMHandle,
[21302]330 destprocess));
[3642]331
332 //TODO: Inheritance of file handles won't work!
333
[4682]334 if(destprocess != srcprocess)
[3714]335 {
336 //TODO:!!!!
337 dprintf(("ERROR: DuplicateHandle; different processes not yet supported!!"));
338 return FALSE;
[3642]339 }
340
[3714]341 if(srcfileinfo)
342 {
[3948]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
[4682]347 if(fdwOdinOptions)
[3714]348 {
[4230]349 HMHANDLEDATA duphdata;
350
[4682]351 memcpy(&duphdata, pHMHandleData, sizeof(duphdata));
352 duphdata.dwCreation = OPEN_EXISTING;
[4230]353
[7549]354 if(CreateFile(srcfileinfo->lpszFileName, &duphdata,
[4682]355 srcfileinfo->lpSecurityAttributes, NULL) == NO_ERROR)
[3948]356 {
[4682]357 memcpy(pHMHandleData, &duphdata, sizeof(duphdata));
[9653]358
[21302]359 SetHandleInformation(pHMHandleData, HANDLE_FLAG_INHERIT, (fInherit) ? HANDLE_FLAG_INHERIT : 0);
[9653]360
[4682]361 SetLastError(ERROR_SUCCESS);
362 return TRUE;
[3948]363 }
[4682]364 dprintf(("ERROR: DuplicateHandle; CreateFile %s failed -> trying DosDupHandle instead!",
[3948]365 srcfileinfo->lpszFileName));
[4682]366 //SvL: IE5 setup opens file with DENYREADWRITE, so CreateFile can't
[4230]367 // be used for duplicating the handle; try DosDupHandle instead
[3714]368 }
[4682]369
[3731]370 if(!(fdwOptions & DUPLICATE_SAME_ACCESS) && fdwAccess != pHMSrcHandle->dwAccess) {
[4682]371 dprintf(("WARNING: DuplicateHandle; app wants different access permission; Not supported!! (%x, %x)", fdwAccess, pHMSrcHandle->dwAccess));
[3731]372 }
[3714]373
[21302]374 pHMHandleData->hHMHandle = 0;
375 rc = OSLibDosDupHandle(pHMSrcHandle->hHMHandle, &pHMHandleData->hHMHandle);
[3714]376 if (rc)
377 {
[9653]378 dprintf(("ERROR: DuplicateHandle: OSLibDosDupHandle(%s) failed = %u",
379 srcfileinfo->lpszFileName, rc));
[3714]380 SetLastError(rc);
381 return FALSE; // ERROR
382 }
[3721]383 else {
[21302]384 SetHandleInformation(pHMHandleData, HANDLE_FLAG_INHERIT, (fInherit) ? HANDLE_FLAG_INHERIT : 0);
[9653]385
[21655]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
[4230]394 SetLastError(ERROR_SUCCESS);
[3714]395 return TRUE; // OK
[3721]396 }
[3642]397 }
[3714]398 else
399 {
[4171]400 dprintf(("ERROR: DuplicateHandle; invalid parameter!!"));
[3714]401 SetLastError(ERROR_INVALID_PARAMETER);
402 return FALSE;
[3642]403 }
404}
405
406/*****************************************************************************
[9653]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 :
[21564]416 * Status :
[9653]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/*****************************************************************************
[5587]444 * Name : BOOL HMDeviceFileClass::CloseHandle
[3642]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
[5587]455BOOL HMDeviceFileClass::CloseHandle(PHMHANDLEDATA pHMHandleData)
[3642]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) {
[4682]466 //TODO: should only do this after all handles have been closed
467 if(fileInfo) {
468 DeleteFileA(fileInfo->lpszFileName);
469 }
[3642]470 }
471 if(fileInfo) {
[4682]472 delete fileInfo;
[3642]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,
[7549]501 LPOVERLAPPED lpOverlapped,
502 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
[3642]503{
504 LPVOID lpRealBuf;
505 Win32MemMap *map;
[3828]506 DWORD offset, bytesread;
[3642]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
[3828]517 //SvL: It's legal for this pointer to be NULL
[3836]518 if(lpNumberOfBytesRead)
519 *lpNumberOfBytesRead = 0;
[4682]520 else
[3836]521 lpNumberOfBytesRead = &bytesread;
[3828]522
[3642]523 if((pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpOverlapped) {
[4682]524 dprintf(("FILE_FLAG_OVERLAPPED flag set, but lpOverlapped NULL!!"));
525 SetLastError(ERROR_INVALID_PARAMETER);
526 return FALSE;
[3642]527 }
528 if(!(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && lpOverlapped) {
[4682]529 dprintf(("Warning: lpOverlapped != NULL & !FILE_FLAG_OVERLAPPED; sync operation"));
[3642]530 }
[7550]531 if(lpCompletionRoutine) {
532 dprintf(("!WARNING!: lpCompletionRoutine not supported -> fall back to sync IO"));
533 }
[3642]534
[4682]535 //SvL: DosRead doesn't like writing to memory addresses returned by
536 // DosAliasMem -> search for original memory mapped pointer and use
[3782]537 // that one + commit pages if not already present
538 map = Win32MemMapView::findMapByView((ULONG)lpBuffer, &offset, MEMMAP_ACCESS_WRITE);
[3642]539 if(map) {
[8121]540 lpRealBuf = (LPVOID)((ULONG)map->getMappingAddr() + offset);
[10564]541 DWORD nrpages = nNumberOfBytesToRead/4096;
[9911]542 if((nNumberOfBytesToRead+offset) & 0xfff)
[8121]543 nrpages++;
[3642]544
[9911]545 map->commitRange((ULONG)lpBuffer, offset & ~0xfff, TRUE, nrpages);
[9824]546 map->Release();
[3642]547 }
[8121]548 else lpRealBuf = (LPVOID)lpBuffer;
[3642]549
[9911]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);
[21667]558 map->Release();
[9911]559 }
560
[3642]561 if(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) {
[4682]562 dprintf(("ERROR: Overlapped IO not yet implememented!!"));
[3642]563 }
564// else {
[4682]565 bRC = OSLibDosRead(pHMHandleData->hHMHandle,
[3642]566 (PVOID)lpRealBuf,
567 nNumberOfBytesToRead,
568 lpNumberOfBytesRead);
569// }
570
571 if(bRC == 0) {
[4682]572 dprintf(("KERNEL32: HMDeviceFileClass::ReadFile returned %08xh %x\n",
[3642]573 bRC, GetLastError()));
[4682]574 dprintf(("%x -> %d", lpBuffer, IsBadWritePtr((LPVOID)lpBuffer, nNumberOfBytesToRead)));
[3642]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,
[7549]601 LPOVERLAPPED lpOverlapped,
602 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
[3642]603{
[3782]604 LPVOID lpRealBuf;
605 Win32MemMap *map;
[3828]606 DWORD offset, byteswritten;
[3782]607 BOOL bRC;
[3642]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
[3828]617 //SvL: It's legal for this pointer to be NULL
[3836]618 if(lpNumberOfBytesWritten)
619 *lpNumberOfBytesWritten = 0;
[4682]620 else
[3836]621 lpNumberOfBytesWritten = &byteswritten;
[3828]622
[3642]623 if((pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && !lpOverlapped) {
[4682]624 dprintf(("FILE_FLAG_OVERLAPPED flag set, but lpOverlapped NULL!!"));
625 SetLastError(ERROR_INVALID_PARAMETER);
626 return FALSE;
[3642]627 }
628 if(!(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) && lpOverlapped) {
[4682]629 dprintf(("Warning: lpOverlapped != NULL & !FILE_FLAG_OVERLAPPED; sync operation"));
[3642]630 }
631
[4682]632 //SvL: DosWrite doesn't like reading from memory addresses returned by
633 // DosAliasMem -> search for original memory mapped pointer and use
[3782]634 // that one + commit pages if not already present
635 map = Win32MemMapView::findMapByView((ULONG)lpBuffer, &offset, MEMMAP_ACCESS_READ);
636 if(map) {
[8121]637 lpRealBuf = (LPVOID)((ULONG)map->getMappingAddr() + offset);
[10564]638 DWORD nrpages = nNumberOfBytesToWrite/4096;
[9911]639 if((nNumberOfBytesToWrite+offset) & 0xfff)
[8121]640 nrpages++;
[21564]641
[21302]642 map->commitRange((ULONG)lpBuffer, offset & ~0xfff, FALSE, nrpages);
[9824]643 map->Release();
[3782]644 }
[8121]645 else lpRealBuf = (LPVOID)lpBuffer;
[3782]646
[3642]647 if(pHMHandleData->dwFlags & FILE_FLAG_OVERLAPPED) {
[4682]648 dprintf(("ERROR: Overlapped IO not yet implememented!!"));
[3642]649 }
650// else {
[4682]651 bRC = OSLibDosWrite(pHMHandleData->hHMHandle,
[3782]652 (PVOID)lpRealBuf,
[3642]653 nNumberOfBytesToWrite,
654 lpNumberOfBytesWritten);
655// }
656
[21667]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 }
[9911]669 }
670
[3642]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/*****************************************************************************
[22024]701 * Name : BOOL HMDeviceFileClass::GetFileInformationByHandle
[3642]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
[22024]713BOOL HMDeviceFileClass::GetFileInformationByHandle(PHMHANDLEDATA pHMHandleData,
714 BY_HANDLE_FILE_INFORMATION* pHFI)
[3642]715{
[4682]716 dprintfl(("KERNEL32: HMDeviceFileClass::GetFileInformationByHandle %s(%08xh,%08xh)\n",
717 lpHMDeviceName, pHMHandleData, pHFI));
[3642]718
[21564]719 HMFileInfo *fileInfo = (HMFileInfo *)pHMHandleData->dwUserData;
720 if(OSLibDosGetFileInformationByHandle(fileInfo->lpszFileName,
721 pHMHandleData->hHMHandle,
[4682]722 pHFI))
723 {
724 return TRUE;
725 }
726 dprintf(("GetFileInformationByHandle failed with error %d", GetLastError()));
727 return FALSE;
[3642]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{
[4682]745 dprintfl(("KERNEL32: HMDeviceFileClass::SetEndOfFile %s(%08xh)\n",
746 lpHMDeviceName,
747 pHMHandleData));
[3642]748
[4682]749 if(OSLibDosSetEndOfFile(pHMHandleData->hHMHandle)) {
750 return TRUE;
751 }
752 dprintf(("SetEndOfFile failed with error %d", GetLastError()));
753 return FALSE;
[3642]754}
755
[9530]756//******************************************************************************
[3642]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 *
[9530]769 * Author : Patrick Haller [Wed, 1999/06/17 20:44] mod. DT
[3642]770 *****************************************************************************/
771
772BOOL HMDeviceFileClass::SetFileTime(PHMHANDLEDATA pHMHandleData,
773 LPFILETIME pFT1,
774 LPFILETIME pFT2,
775 LPFILETIME pFT3)
776{
[4682]777 dprintfl(("KERNEL32: HMDeviceFileClass::SetFileTime %s(%08xh,%08xh,%08xh,%08xh)\n",
778 lpHMDeviceName, pHMHandleData, pFT1, pFT2, pFT3));
[3642]779
[9530]780 if(OSLibDosSetFileTime(pHMHandleData->hHMHandle, pFT1, pFT2, pFT3)) return TRUE;
[3642]781
[4682]782 dprintf(("SetFileTime failed with error %d", GetLastError()));
783 return FALSE;
[3642]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 *
[9530]798 * Author : SvL mod. DT
[3642]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?
[4682]807 dprintf(("ERROR: GetFileTime: invalid parameter!"));
808 SetLastError(ERROR_INVALID_PARAMETER);
809 return FALSE;
[3642]810 }
811
[9530]812 if(OSLibDosGetFileTime(pHMHandleData->hHMHandle, pFT1, pFT2, pFT3)) return TRUE;
[3642]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;
[21302]865 HMFileInfo *fileInfo = (HMFileInfo *)pHMHandleData->dwUserData;
[3642]866
867 dprintfl(("KERNEL32: HMDeviceFileClass::SetFilePointer %s(%08xh,%08xh,%08xh,%08xh)\n",
868 lpHMDeviceName,
869 pHMHandleData,
870 lDistanceToMove,
871 lpDistanceToMoveHigh,
872 dwMoveMethod));
873
[21329]874 if(fileInfo && fileInfo->dwLXOffset)
[21302]875 {
[21564]876 switch(dwMoveMethod)
[21302]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 }
[21329]891
[3642]892 ret = OSLibDosSetFilePointer(pHMHandleData->hHMHandle,
893 lDistanceToMove,
894 (DWORD *)lpDistanceToMoveHigh,
895 dwMoveMethod);
896
897 if(ret == -1) {
[4682]898 dprintf(("SetFilePointer failed (error = %d)", GetLastError()));
[3642]899 }
900 return ret;
901}
902
903
904/*****************************************************************************
[9975]905 * Name : BOOL HMDeviceFileClass::LockFile
[3642]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
[3765]920BOOL HMDeviceFileClass::LockFile(PHMHANDLEDATA pHMHandleData,
[3642]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
[3765]960BOOL HMDeviceFileClass::LockFileEx(PHMHANDLEDATA pHMHandleData,
[3642]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
[3765]1004BOOL HMDeviceFileClass::UnlockFile(PHMHANDLEDATA pHMHandleData,
[3642]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
[3765]1045BOOL HMDeviceFileClass::UnlockFileEx(PHMHANDLEDATA pHMHandleData,
1046 DWORD dwReserved,
1047 DWORD nNumberOfBytesToLockLow,
1048 DWORD nNumberOfBytesToLockHigh,
1049 LPOVERLAPPED lpOverlapped)
[3642]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}
[10073]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
[21564]1129 * Remark :
[10073]1130 * Status :
1131 *
1132 * Author : SvL
1133 ******************************************************************************/
1134BOOL HMDeviceFileClass::GetFileNameFromHandle(PHMHANDLEDATA pHMHandleData,
1135 LPSTR lpszFileName, DWORD cbFileName)
1136{
1137 HMFileInfo *fileInfo = (HMFileInfo *)pHMHandleData->dwUserData;
[10064]1138
[10073]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
[3642]1148//******************************************************************************
1149//******************************************************************************
[10064]1150// File information handle class
1151//
1152// When the application opens a file with CreateFile and 0 for desired access,
[21564]1153// then we need to create a handle with limited access.
[10064]1154//
1155// MSDN:
1156//
[21564]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
[10064]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 :
[21564]1176 * Remark :
[10064]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));
[21564]1196
[10064]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
[22025]1209 pHMHandleData->dwUserData = (DWORD) new HMFileInfo(INVALID_HANDLE_VALUE,
1210 (LPSTR)lpFileName, lpSecurityAttributes);
1211 pHMHandleData->hHMHandle = 0x80000000; // make sure _HMHandleQuery won't fail
[10064]1212 return (NO_ERROR);
1213
1214}
1215/******************************************************************************
1216 * Name : BOOL HMDeviceFileClass::CloseHandle
1217 * Purpose : close the handle
1218 * Parameters: PHMHANDLEDATA pHMHandleData
1219 * Variables :
1220 * Result : API returncode
1221 * Remark :
1222 * Status :
1223 *
1224 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
1225 *****************************************************************************/
1226BOOL HMDeviceInfoFileClass::CloseHandle(PHMHANDLEDATA pHMHandleData)
1227{
1228 HMFileInfo *fileInfo = (HMFileInfo *)pHMHandleData->dwUserData;
1229
1230 dprintfl(("KERNEL32: HMDeviceInfoFileClass::CloseHandle(%08x)\n",
1231 pHMHandleData->hHMHandle));
1232
1233 if(fileInfo) {
1234 delete fileInfo;
1235 }
1236 return TRUE;
1237}
1238/******************************************************************************
1239 * Name : BOOL HMDeviceInfoFileClass::GetFileTime
1240 * Purpose : Get file time
1241 * Parameters: PHMHANDLEDATA pHMHandleData
1242 * PFILETIME pFT1
1243 * PFILETIME pFT2
1244 * PFILETIME pFT3
1245 * Variables :
1246 * Result : API returncode
1247 * Remark :
1248 * Status :
1249 *
1250 * Author : SvL
1251 *****************************************************************************/
1252BOOL HMDeviceInfoFileClass::GetFileTime (PHMHANDLEDATA pHMHandleData,
1253 LPFILETIME pFT1,
1254 LPFILETIME pFT2,
1255 LPFILETIME pFT3)
1256{
1257 HMFileInfo *fileInfo = (HMFileInfo *)pHMHandleData->dwUserData;
1258
1259 if(!pFT1 && !pFT2 && !pFT3) {//TODO: does NT do this?
1260 dprintf(("ERROR: GetFileTime: invalid parameter!"));
1261 SetLastError(ERROR_INVALID_PARAMETER);
1262 return FALSE;
1263 }
1264 WIN32_FIND_DATAA finddata;
1265 HANDLE hFind;
[21564]1266
[10064]1267 hFind = FindFirstFileA(fileInfo->lpszFileName, &finddata);
1268 if(hFind == INVALID_HANDLE_VALUE) {
1269 return GetLastError();
1270 }
1271 if(pFT1) {
1272 *pFT1 = finddata.ftCreationTime;
1273 }
1274 if(pFT2) {
1275 *pFT2 = finddata.ftLastAccessTime;
1276 }
1277 if(pFT3) {
1278 *pFT3 = finddata.ftLastWriteTime;
1279 }
1280 FindClose(hFind);
1281 SetLastError(ERROR_SUCCESS);
1282 return TRUE;
1283}
1284/******************************************************************************
1285 * Name : DWORD HMDeviceInfoFileClass::GetFileSize
1286 * Purpose : get file size
1287 * Parameters: PHMHANDLEDATA pHMHandleData
1288 * PDWORD pSize
1289 * Variables :
1290 * Result : API returncode
1291 * Remark : Doesn't fail for directories; just returns 0 (verified in NT4, SP6)
1292 * Status :
1293 *
1294 * Author : SvL
1295 *****************************************************************************/
1296DWORD HMDeviceInfoFileClass::GetFileSize(PHMHANDLEDATA pHMHandleData,
1297 PDWORD lpdwFileSizeHigh)
1298{
1299 HMFileInfo *fileInfo = (HMFileInfo *)pHMHandleData->dwUserData;
1300
1301 SetLastError(ERROR_SUCCESS);
1302
1303 if(lpdwFileSizeHigh)
1304 *lpdwFileSizeHigh = 0;
1305
1306 if(fileInfo == NULL) {
1307 DebugInt3();
1308 SetLastError(ERROR_INVALID_PARAMETER); //TODO
1309 return -1; //INVALID_FILE_SIZE;
1310 }
1311
1312 WIN32_FIND_DATAA finddata;
1313 HANDLE hFind;
[21564]1314
[10064]1315 hFind = FindFirstFileA(fileInfo->lpszFileName, &finddata);
1316 if(hFind == INVALID_HANDLE_VALUE) {
1317 return GetLastError();
1318 }
1319 if(lpdwFileSizeHigh) {
1320 *lpdwFileSizeHigh = finddata.nFileSizeHigh;
1321 }
1322 FindClose(hFind);
[21302]1323
[21564]1324 if(fileInfo->dwLXOffset)
[21302]1325 {
1326 //subtract the LX header and magic qword from the file size
1327 dprintf(("GetFileSize (LX) -> change size from %x to %x", finddata.nFileSizeLow, finddata.nFileSizeLow-fileInfo->dwLXOffset-MAGIC_STUBEXE_SIZE));
1328 finddata.nFileSizeLow -= (fileInfo->dwLXOffset+MAGIC_STUBEXE_SIZE);
1329 }
[10064]1330 return finddata.nFileSizeLow;
1331}
[22025]1332/*****************************************************************************
1333 * Name : BOOL HMDeviceFileInfoClass::GetFileInformationByHandle
1334 * Purpose : determine the handle type
1335 * Parameters: PHMHANDLEDATA pHMHandleData
1336 * BY_HANDLE_FILE_INFORMATION* pHFI
1337 * Variables :
1338 * Result : API returncode
1339 * Remark :
1340 * Status :
1341 *****************************************************************************/
1342
1343BOOL HMDeviceInfoFileClass::GetFileInformationByHandle(PHMHANDLEDATA pHMHandleData,
1344 BY_HANDLE_FILE_INFORMATION* pHFI)
1345{
1346 dprintfl(("KERNEL32: HMDeviceInfoFileClass::GetFileInformationByHandle %s(%08xh,%08xh)\n",
1347 lpHMDeviceName, pHMHandleData, pHFI));
1348
1349 HMFileInfo *fileInfo = (HMFileInfo *)pHMHandleData->dwUserData;
1350 if(OSLibDosGetFileInformationByHandle(fileInfo->lpszFileName,
1351 INVALID_HANDLE_VALUE,
1352 pHFI))
1353 {
1354 return TRUE;
1355 }
1356 dprintf(("GetFileInformationByHandle failed with error %d", GetLastError()));
1357 return FALSE;
1358}
[10064]1359/******************************************************************************
[10073]1360 * Name : DWORD HMDeviceFileClass::GetFileNameFromHandle
1361 * Purpose : the name of the file associated with the system handle (if any)
1362 * Parameters: PHMHANDLEDATA pHMHandleData
1363 * Variables :
1364 * Result : BOOLEAN
[21564]1365 * Remark :
[10073]1366 * Status :
1367 *
1368 * Author : SvL
1369 ******************************************************************************/
1370BOOL HMDeviceInfoFileClass::GetFileNameFromHandle(PHMHANDLEDATA pHMHandleData,
1371 LPSTR lpszFileName, DWORD cbFileName)
1372{
1373 HMFileInfo *fileInfo = (HMFileInfo *)pHMHandleData->dwUserData;
1374
1375 if(fileInfo == NULL || strlen(fileInfo->lpszFileName) >= cbFileName) {
1376 if(fileInfo) DebugInt3();
1377 return FALSE;
1378 }
1379 strcpy(lpszFileName, fileInfo->lpszFileName);
1380
1381 return TRUE;
1382}
1383/******************************************************************************
[10064]1384 * Name : DWORD HMDeviceFileClass::GetFileType
1385 * Purpose : determine the handle type
1386 * Parameters: PHMHANDLEDATA pHMHandleData
1387 * Variables :
1388 * Result : API returncode
1389 * Remark : Returns FILE_TYPE_DISK for both files and directories
1390 * Status :
1391 *
1392 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
1393 ******************************************************************************/
1394DWORD HMDeviceInfoFileClass::GetFileType(PHMHANDLEDATA pHMHandleData)
1395{
1396 dprintfl(("KERNEL32: HMDeviceInfoFileClass::GetFileType %s(%08x)\n",
1397 lpHMDeviceName,
1398 pHMHandleData));
1399
1400 return FILE_TYPE_DISK;
1401}
1402//******************************************************************************
1403//******************************************************************************
[21302]1404HMFileInfo::HMFileInfo(HANDLE hFile, LPSTR lpszFileName, PVOID lpSecurityAttributes)
[3642]1405{
[21564]1406 // get the full path (this is necessary in particular for GetFileInformationByHandle)
1407 char fullPath[260];
1408 if (!OSLibDosQueryPathInfo(lpszFileName, FIL_QUERYFULLNAME, fullPath, sizeof(fullPath))) {
1409 lpszFileName = fullPath;
1410 }
1411
[3642]1412 this->lpszFileName = (LPSTR)malloc(strlen(lpszFileName)+1);
1413 if(!this->lpszFileName) {
[4682]1414 DebugInt3();
[3642]1415 }
1416 strcpy(this->lpszFileName, lpszFileName);
1417 this->lpSecurityAttributes = lpSecurityAttributes;
[21302]1418 dwLXOffset = 0;
1419
1420 //Only check files that end with .exe for now; they might be prepended with
1421 //an LX header. We need to skip that to present the original file to the
1422 //caller
[22025]1423 if((hFile != INVALID_HANDLE_VALUE) && !stricmp(lpszFileName + strlen(lpszFileName) - 4, ".EXE"))
[21302]1424 {
1425 ULONG action, ulRead, signature, ulFileSize;
1426 ULONG magic[2];
1427 IMAGE_DOS_HEADER doshdr;
1428
1429 //read dos header
1430 if(!OSLibDosRead(hFile, (LPVOID)&doshdr, sizeof(doshdr), &ulRead)) {
1431 goto failure;
1432 }
1433 if(OSLibDosSetFilePointer(hFile, doshdr.e_lfanew, NULL, FILE_BEGIN) != doshdr.e_lfanew) {
1434 goto failure;
1435 }
1436 //read signature dword
1437 if(!OSLibDosRead(hFile, (LPVOID)&signature, sizeof(signature), &ulRead)) {
1438 goto failure;
1439 }
1440
1441 //Make sure it's an LX executable before continueing
[21564]1442 if(doshdr.e_magic != IMAGE_DOS_SIGNATURE || (WORD)signature != IMAGE_OS2_SIGNATURE_LX)
[21302]1443 {
1444 goto failure;
1445 }
1446
1447 //magic signature located at 8 bytes from file end
1448 if(OSLibDosSetFilePointer(hFile, -8, NULL, FILE_END) == -1) {
1449 goto failure;
1450 }
1451 //read magic signature + pe offset
1452 if(!OSLibDosRead(hFile, (LPVOID)&magic[0], sizeof(magic), &ulRead)) {
1453 goto failure;
1454 }
1455 if(magic[0] != MAGIC_STUBEXE_SIGNATURE || magic[1] > ulFileSize) {
1456 goto failure;
1457 }
1458 //this is the offset of the PE image inside our LX executable
1459 dwLXOffset = magic[1];
1460
1461 dprintf(("LX wrapper: PE file %s starts at %x", lpszFileName, dwLXOffset));
1462 //reset file pointer to PE image start
1463 if(OSLibDosSetFilePointer(hFile, dwLXOffset, NULL, FILE_BEGIN) != dwLXOffset) {
1464 DebugInt3();
1465 }
1466 goto end;
1467
1468failure:
1469 //reset file pointer to file start
1470 if(OSLibDosSetFilePointer(hFile, 0, NULL, FILE_BEGIN) != 0) {
1471 DebugInt3();
1472 }
1473 }
1474end:
1475 return;
[3642]1476}
1477//******************************************************************************
1478//******************************************************************************
1479HMFileInfo::~HMFileInfo()
1480{
1481 if(lpszFileName) {
[4682]1482 free(lpszFileName);
1483 lpszFileName = NULL;
[3642]1484 }
1485}
[10064]1486
1487//*****************************************************************************
1488//Parses and copies path
1489//OpenFile in NT4, SP6 accepts double (or more) backslashes as separators for directories!
1490//(OS/2 doesn't)
1491//Girotel 2.0 (Dutch banking app) seems to depend on this behaviour
1492//*****************************************************************************
1493static void ParsePath(LPCSTR lpszFileName, LPSTR lpszParsedFileName, DWORD length)
1494{
1495 int i=0;
1496
1497 while(*lpszFileName != 0 && i < length-1) {
1498 *lpszParsedFileName++ = *lpszFileName;
1499 if(*lpszFileName == '\\') {
1500 while(*lpszFileName == '\\') {
1501 lpszFileName++;
1502 }
1503 }
1504 else {
1505 lpszFileName++;
1506 }
1507 i++;
1508 }
1509 *lpszParsedFileName = 0;
1510}
[3642]1511//******************************************************************************
1512//******************************************************************************
Note: See TracBrowser for help on using the repository browser.