source: trunk/src/kernel32/oslibdos.cpp@ 4771

Last change on this file since 4771 was 4771, checked in by phaller, 25 years ago

Accelerated FindFirst/FindNext calls

File size: 71.3 KB
Line 
1/* $Id: oslibdos.cpp,v 1.54 2000-12-09 16:16:26 phaller Exp $ */
2/*
3 * Wrappers for OS/2 Dos* API
4 *
5 * Copyright 1998-2000 Sander van Leeuwen (sandervl@xs4all.nl)
6 * Copyright 1999-2000 Edgar Buerkle (Edgar.Buerkle@gmx.net)
7 * Copyright 2000 Przemyslaw Dobrowolski (dobrawka@asua.org.pl)
8 * Copyright 2000 Christoph Bratschi (cbratschi@datacomm.ch)
9 * Copyright 2000 knut st. osmundsen (knut.stange.osmundsen@mynd.no)
10 *
11 * Project Odin Software License can be found in LICENSE.TXT
12 *
13 */
14#define INCL_BASE
15#define INCL_DOSEXCEPTIONS
16#define INCL_DOSMEMMGR
17#define INCL_DOSPROCESS
18#define INCL_DOSFILEMGR
19#define INCL_DOSERRORS
20#define INCL_DOSDEVIOCTL
21#define INCL_NPIPES
22#include <os2wrap.h> //Odin32 OS/2 api wrappers
23#include <stdlib.h>
24#include <stdio.h>
25#include <string.h>
26#include <ctype.h>
27#include <win32api.h>
28#include <winconst.h>
29#include <misc.h>
30#include "initterm.h"
31#include "oslibdos.h"
32#include "dosqss.h"
33
34#define DBG_LOCALLOG DBG_oslibdos
35#include "dbglocal.h"
36
37static PROC_DosSetFileSizeL DosSetFileSizeLProc = 0;
38static PROC_DosSetFilePtrL DosSetFilePtrLProc = 0;
39static PROC_DosSetFileLocksL DosSetFileLocksLProc = 0;
40static BOOL f64BitIO = FALSE;
41//******************************************************************************
42//******************************************************************************
43void OSLibInitWSeBFileIO()
44{
45 HMODULE hDoscalls;
46
47 if(DosQueryModuleHandle("DOSCALLS", &hDoscalls) != NO_ERROR) {
48 return;
49 }
50 if(DosQueryProcAddr(hDoscalls, 989, NULL, (PFN *)&DosSetFileSizeLProc) != NO_ERROR) {
51 return;
52 }
53 if(DosQueryProcAddr(hDoscalls, 988, NULL, (PFN *)&DosSetFilePtrLProc) != NO_ERROR) {
54 return;
55 }
56 if(DosQueryProcAddr(hDoscalls, 986, NULL, (PFN *)&DosSetFileLocksLProc) != NO_ERROR) {
57 return;
58 }
59 f64BitIO = TRUE;
60}
61//******************************************************************************
62//******************************************************************************
63APIRET OdinDosSetFileSizeL(HFILE hFile, LONGLONG cbSize)
64{
65 APIRET yyrc;
66 USHORT sel = RestoreOS2FS();
67
68 yyrc = DosSetFileSizeLProc(hFile, cbSize);
69 SetFS(sel);
70
71 return yyrc;
72}
73//******************************************************************************
74//******************************************************************************
75APIRET OdinDosSetFilePtrL(HFILE hFile, LONGLONG ib, ULONG method, PLONGLONG ibActual)
76{
77 APIRET yyrc;
78 USHORT sel = RestoreOS2FS();
79
80 yyrc = DosSetFilePtrLProc(hFile, ib, method, ibActual);
81 SetFS(sel);
82
83 return yyrc;
84}
85//******************************************************************************
86//******************************************************************************
87APIRET OdinDosSetFileLocksL(HFILE hFile, PFILELOCKL pflUnlock, PFILELOCKL pflLock,
88 ULONG timeout, ULONG flags)
89{
90 APIRET yyrc;
91 USHORT sel = RestoreOS2FS();
92
93 yyrc = DosSetFileLocksLProc(hFile, pflUnlock, pflLock, timeout, flags);
94 SetFS(sel);
95
96 return yyrc;
97}
98//******************************************************************************
99// translate OS/2 error codes to Windows codes
100// NOTE: add all codes you need, list is not complete!
101//******************************************************************************
102DWORD error2WinError(APIRET rc,DWORD defaultCode = ERROR_NOT_ENOUGH_MEMORY_W)
103{
104 switch (rc)
105 {
106 case NO_ERROR: //0
107 return ERROR_SUCCESS_W;
108
109 case ERROR_INVALID_FUNCTION: //1
110 return ERROR_INVALID_FUNCTION_W;
111
112 case ERROR_FILE_NOT_FOUND: //2
113 return ERROR_FILE_NOT_FOUND_W;
114
115 case ERROR_PATH_NOT_FOUND: //3
116 return ERROR_PATH_NOT_FOUND_W;
117
118 case ERROR_TOO_MANY_OPEN_FILES: //4
119 return ERROR_TOO_MANY_OPEN_FILES_W;
120
121 case ERROR_ACCESS_DENIED: //5
122 return ERROR_ACCESS_DENIED_W;
123
124 case ERROR_INVALID_HANDLE: //6
125 return ERROR_INVALID_HANDLE_W;
126
127 case ERROR_NOT_ENOUGH_MEMORY: //8
128 return ERROR_NOT_ENOUGH_MEMORY_W;
129
130 case ERROR_BAD_FORMAT: //11
131 return ERROR_BAD_FORMAT_W;
132
133 case ERROR_INVALID_ACCESS: //12
134 return ERROR_INVALID_ACCESS_W;
135
136 case ERROR_NO_MORE_FILES: //18
137 return ERROR_NO_MORE_FILES_W;
138
139 case ERROR_WRITE_PROTECT: //19
140 return ERROR_WRITE_PROTECT_W;
141
142 case ERROR_NOT_DOS_DISK: //26
143 return ERROR_NOT_DOS_DISK_W;
144
145 case ERROR_WRITE_FAULT: //29
146 return ERROR_WRITE_FAULT_W;
147
148 case ERROR_SHARING_VIOLATION: //32
149 return ERROR_SHARING_VIOLATION_W;
150
151 case ERROR_LOCK_VIOLATION: //32
152 return ERROR_LOCK_VIOLATION_W;
153
154 case ERROR_SHARING_BUFFER_EXCEEDED: //36
155 return ERROR_SHARING_BUFFER_EXCEEDED_W;
156
157 case ERROR_CANNOT_MAKE: //82
158 return ERROR_CANNOT_MAKE_W;
159
160 case ERROR_OUT_OF_STRUCTURES: //84
161 return ERROR_OUT_OF_STRUCTURES_W;
162
163 case ERROR_INVALID_PARAMETER: //87
164 return ERROR_INVALID_PARAMETER_W;
165
166 case ERROR_INTERRUPT: //95
167 return ERROR_INVALID_AT_INTERRUPT_TIME_W; //CB: right???
168
169 case ERROR_DEVICE_IN_USE: //99
170 return ERROR_DEVICE_IN_USE_W;
171
172 case ERROR_DRIVE_LOCKED: //108
173 return ERROR_DRIVE_LOCKED_W;
174
175 case ERROR_BROKEN_PIPE: //109
176 return ERROR_BROKEN_PIPE_W;
177
178 case ERROR_OPEN_FAILED: //110
179 return ERROR_OPEN_FAILED_W;
180
181 case ERROR_BUFFER_OVERFLOW: //111
182 return ERROR_BUFFER_OVERFLOW_W;
183
184 case ERROR_DISK_FULL: //112
185 return ERROR_DISK_FULL_W;
186
187 case ERROR_NO_MORE_SEARCH_HANDLES: //113
188 return ERROR_NO_MORE_SEARCH_HANDLES_W;
189
190 case ERROR_SEM_TIMEOUT: //121
191 return ERROR_SEM_TIMEOUT_W;
192
193 case ERROR_DIRECT_ACCESS_HANDLE: //130
194 return ERROR_DIRECT_ACCESS_HANDLE_W;
195
196 case ERROR_NEGATIVE_SEEK: //131
197 return ERROR_NEGATIVE_SEEK;
198
199 case ERROR_SEEK_ON_DEVICE: //132
200 return ERROR_SEEK_ON_DEVICE_W;
201
202 case ERROR_DISCARDED: //157
203 return ERROR_DISCARDED_W;
204
205 case ERROR_FILENAME_EXCED_RANGE: //206
206 return ERROR_FILENAME_EXCED_RANGE_W;
207
208 case ERROR_META_EXPANSION_TOO_LONG: //208
209 return ERROR_META_EXPANSION_TOO_LONG_W;
210
211 case ERROR_BAD_PIPE: //230
212 return ERROR_BAD_PIPE_W;
213
214 case ERROR_PIPE_BUSY: //231
215 return ERROR_PIPE_BUSY_W;
216
217 case ERROR_NO_DATA: //232
218 return ERROR_NO_DATA_W;
219
220 case ERROR_PIPE_NOT_CONNECTED: //233
221 return ERROR_PIPE_NOT_CONNECTED_W;
222
223 case ERROR_MORE_DATA: //234
224 return ERROR_MORE_DATA_W;
225
226 case ERROR_INVALID_EA_NAME: //254
227 return ERROR_INVALID_EA_NAME_W;
228
229 case ERROR_EA_LIST_INCONSISTENT: //255
230 return ERROR_EA_LIST_INCONSISTENT_W;
231
232 case ERROR_EAS_DIDNT_FIT: //275
233 return ERROR_EAS_DIDNT_FIT;
234
235 default:
236 dprintf(("WARNING: error2WinError: error %d not included!!!!", rc));
237 return defaultCode;
238 }
239}
240//******************************************************************************
241//TODO: Assumes entire memory range has the same protection flags!
242//TODO: Check if this works for code aliases...
243//******************************************************************************
244DWORD OSLibDosAliasMem(LPVOID pb, ULONG cb, LPVOID *ppbAlias, ULONG fl)
245{
246 DWORD rc;
247 DWORD attr;
248 DWORD size = cb;
249
250 cb = (cb-1) & ~0xfff;
251 cb+= PAGE_SIZE;
252
253 rc = DosQueryMem(pb, &size, &attr);
254 if(rc) {
255 dprintf(("OSLibDosAliasMem: DosQueryMem %x %x return %d", pb, size, rc));
256 return rc;
257 }
258 size = (size-1) & ~0xfff;
259 size+= PAGE_SIZE;
260 if(size != cb) {
261 dprintf(("ERROR: OSLibDosAliasMem: size != cb (%x!=%x)!!!!!!!!", size, cb));
262 //ignore this and continue return 5;
263 attr = fl; //just use original protection flags (NOT CORRECT)
264 }
265 attr &= (PAG_READ|PAG_WRITE|PAG_EXECUTE|PAG_GUARD|PAG_DEFAULT);
266 if(attr != fl) {
267 rc = DosSetMem(pb, size, fl);
268 if(rc) {
269 dprintf(("OSLibDosAliasMem: DosSetMem %x %x return %d", pb, size, rc));
270 attr = fl;
271 //just continue for now
272 //return rc;
273 }
274 }
275 rc = DosAliasMem(pb, cb, ppbAlias, 2);
276 if(rc) {
277 dprintf(("OSLibDosAliasMem: DosAliasMem %x %x returned %d", pb, cb, rc));
278 return rc;
279 }
280 if(attr != fl) {
281 rc = DosSetMem(pb, size, attr);
282 if(rc) {
283 dprintf(("OSLibDosAliasMem: DosSetMem (2) %x %x return %d", pb, size, rc));
284 return rc;
285 }
286 }
287 return 0;
288}
289//******************************************************************************
290//NT returns addresses aligned at 64k, so we do too.
291//******************************************************************************
292DWORD OSLibDosAllocMem(LPVOID *lplpMemAddr, DWORD size, DWORD flags)
293{
294 LPVOID memaddr;
295 DWORD offset;
296 APIRET rc;
297
298 rc = DosAllocMem(&memaddr, size, PAG_READ | flAllocMem);
299 if(rc) {
300 return rc;
301 }
302 DosEnterCritSec();
303 DosFreeMem(memaddr);
304 offset = (DWORD)memaddr & 0xFFFF;
305 if(offset) {
306 DosAllocMem(&memaddr, 64*1024 - offset, PAG_READ | flAllocMem);
307 }
308 rc = DosAllocMem(lplpMemAddr, size, flags | flAllocMem);
309 DosExitCritSec();
310 if((DWORD)*lplpMemAddr & 0xFFFF) {//still not at 64k boundary?
311 DosFreeMem(*lplpMemAddr);
312 rc = OSLibDosAllocMem(lplpMemAddr, size, flags);
313 }
314 if(offset) {
315 DosFreeMem(memaddr);
316 }
317
318 return rc;
319}
320//******************************************************************************
321//******************************************************************************
322DWORD OSLibDosFreeMem(LPVOID lpMemAddr)
323{
324 return DosFreeMem(lpMemAddr);
325}
326//******************************************************************************
327//NOTE: If name == NULL, allocated gettable unnamed shared memory
328//OS/2 returns error 123 (invalid name) if the shared memory name includes
329//colons. We need to replace them with underscores.
330//******************************************************************************
331DWORD OSLibDosAllocSharedMem(LPVOID *lplpMemAddr, DWORD size, DWORD flags, LPSTR name)
332{
333 APIRET rc;
334 char *sharedmemname = NULL, *tmp;
335
336 if(name) {
337 sharedmemname = (char *)malloc(strlen(name) + 16);
338 strcpy(sharedmemname, "\\SHAREMEM\\");
339 strcat(sharedmemname, name);
340 }
341 else flags |= OBJ_GETTABLE;
342
343 //SvL: Colons are unacceptable in shared memory names (for whatever reason)
344 tmp = sharedmemname;
345 while(*tmp != 0) {
346 if(*tmp == ':') {
347 *tmp = '_';
348 }
349 tmp++;
350 }
351
352 rc = DosAllocSharedMem(lplpMemAddr, sharedmemname, size, flags);
353 if(name) {
354 free(sharedmemname);
355 }
356 return rc;
357}
358//******************************************************************************
359//NOTE: If name == NULL, assume gettable unnamed shared memory
360//******************************************************************************
361DWORD OSLibDosGetNamedSharedMem(LPVOID *lplpMemAddr, LPSTR name)
362{
363 APIRET rc;
364 char *sharedmemname = NULL, *tmp;
365
366 if(name) {
367 sharedmemname = (char *)malloc(strlen(name) + 16);
368 strcpy(sharedmemname, "\\SHAREMEM\\");
369 strcat(sharedmemname, name);
370
371 //SvL: Colons are unacceptable in shared memory names (for whatever reason)
372 tmp = sharedmemname;
373 while(*tmp != 0) {
374 if(*tmp == ':') {
375 *tmp = '_';
376 }
377 tmp++;
378 }
379 rc = DosGetNamedSharedMem(lplpMemAddr, sharedmemname, PAG_READ|PAG_WRITE);
380 if(name) {
381 free(sharedmemname);
382 }
383 }
384 else rc = DosGetSharedMem((LPVOID)*(DWORD *)lplpMemAddr, PAG_READ|PAG_WRITE);
385
386 return rc;
387}
388//******************************************************************************
389//******************************************************************************
390DWORD OSLibDosQueryMem(LPVOID lpMemAddr, DWORD *lpRangeSize, DWORD *lpAttr)
391{
392 return DosQueryMem(lpMemAddr, lpRangeSize, lpAttr);
393}
394//******************************************************************************
395//******************************************************************************
396DWORD OSLibDosSetMem(LPVOID lpMemAddr, DWORD size, DWORD flags)
397{
398 APIRET rc;
399
400 rc = DosSetMem(lpMemAddr, size, flags);
401 switch(rc) {
402 case ERROR_INVALID_ADDRESS:
403 return OSLIB_ERROR_INVALID_ADDRESS;
404 case ERROR_ACCESS_DENIED:
405 return OSLIB_ERROR_ACCESS_DENIED;
406 default:
407 return rc;
408 }
409}
410//******************************************************************************
411//******************************************************************************
412DWORD OSLibDosOpen(char *lpszFileName, DWORD flags)
413{
414 APIRET rc;
415 HFILE hFile;
416 ULONG ulAction;
417 DWORD os2flags = OPEN_FLAGS_NOINHERIT;
418
419
420 if(flags & OSLIB_ACCESS_READONLY)
421 os2flags |= OPEN_ACCESS_READONLY;
422 else
423 if(flags & OSLIB_ACCESS_READWRITE)
424 os2flags |= OPEN_ACCESS_READWRITE;
425
426 if(flags & OSLIB_ACCESS_SHAREDENYNONE)
427 os2flags |= OPEN_SHARE_DENYNONE;
428 else
429 if(flags & OSLIB_ACCESS_SHAREDENYREAD)
430 os2flags |= OPEN_SHARE_DENYREAD;
431 else
432 if(flags & OSLIB_ACCESS_SHAREDENYWRITE)
433 os2flags |= OPEN_SHARE_DENYWRITE;
434
435tryopen:
436 rc = DosOpen(lpszFileName, /* File path name */
437 &hFile, /* File handle */
438 &ulAction, /* Action taken */
439 0L, /* File primary allocation */
440 0L, /* File attribute */
441 OPEN_ACTION_FAIL_IF_NEW |
442 OPEN_ACTION_OPEN_IF_EXISTS, /* Open function type */
443 os2flags,
444 0L); /* No extended attribute */
445
446 if(rc) {
447 if(rc == ERROR_TOO_MANY_OPEN_FILES) {
448 ULONG CurMaxFH;
449 LONG ReqCount = 32;
450
451 rc = DosSetRelMaxFH(&ReqCount, &CurMaxFH);
452 if(rc) {
453 dprintf(("DosSetRelMaxFH returned %d", rc));
454 return 0;
455 }
456 dprintf(("DosOpen failed -> increased nr open files to %d", CurMaxFH));
457 goto tryopen;
458 }
459 return 0;
460 }
461 else return hFile;
462}
463//******************************************************************************
464//******************************************************************************
465BOOL OSLibDosClose(DWORD hFile)
466{
467 APIRET rc;
468
469 rc = DosClose(hFile);
470 SetLastError(error2WinError(rc));
471 return (rc == NO_ERROR);
472}
473//******************************************************************************
474//******************************************************************************
475DWORD OSLibDosChangeMaxFileHandles()
476{
477 ULONG CurMaxFH;
478 LONG ReqCount = 0;
479 APIRET rc;
480
481 rc = DosSetRelMaxFH(&ReqCount, &CurMaxFH);
482 if(rc) {
483 dprintf(("DosSetRelMaxFH returned %d", rc));
484 return rc;
485 }
486 if(ReqCount + ODIN_INCREMENT_MAX_FILEHANDLES > CurMaxFH) {
487 ReqCount = CurMaxFH + ODIN_INCREMENT_MAX_FILEHANDLES;
488 rc = DosSetRelMaxFH(&ReqCount, &CurMaxFH);
489 if(rc) {
490 dprintf(("DosSetRelMaxFH returned %d", rc));
491 return rc;
492 }
493 }
494 return 0;
495}
496//******************************************************************************
497//******************************************************************************
498DWORD OSLibDosSetInitialMaxFileHandles(DWORD maxhandles)
499{
500 ULONG CurMaxFH;
501 LONG ReqCount = 0;
502 APIRET rc;
503
504 rc = DosSetRelMaxFH(&ReqCount, &CurMaxFH);
505 if(rc) {
506 dprintf(("DosSetRelMaxFH returned %d", rc));
507 return rc;
508 }
509 if(CurMaxFH < maxhandles) {
510 rc = DosSetMaxFH(maxhandles);
511 if(rc) {
512 dprintf(("DosSetMaxFH returned %d", rc));
513 return rc;
514 }
515 }
516 return 0;
517}
518//******************************************************************************
519//******************************************************************************
520BOOL OSLibDosRead(DWORD hFile, LPVOID lpBuffer, DWORD size, DWORD *nrBytesRead)
521{
522 APIRET rc;
523
524 rc = DosRead(hFile, lpBuffer, size, nrBytesRead);
525 SetLastError(error2WinError(rc));
526 return (rc == NO_ERROR);
527}
528//******************************************************************************
529//******************************************************************************
530BOOL OSLibDosWrite(DWORD hFile, LPVOID lpBuffer, DWORD size, DWORD *nrBytesWritten)
531{
532 APIRET rc;
533
534 rc = DosWrite(hFile, lpBuffer, size, nrBytesWritten);
535 SetLastError(error2WinError(rc));
536 return (rc == NO_ERROR);
537}
538//******************************************************************************
539//******************************************************************************
540DWORD OSLibDosSetFilePtr(DWORD hFile, DWORD offset, DWORD method)
541{
542 DWORD os2method;
543 DWORD newoffset;
544 APIRET rc;
545
546 switch(method)
547 {
548 case OSLIB_SETPTR_FILE_CURRENT:
549 os2method = FILE_CURRENT;
550 break;
551 case OSLIB_SETPTR_FILE_BEGIN:
552 os2method = FILE_BEGIN ;
553 break;
554 case OSLIB_SETPTR_FILE_END:
555 os2method = FILE_END;
556 break;
557 default:
558 return OSLIB_ERROR_INVALID_PARAMETER;
559 }
560
561 rc = DosSetFilePtr(hFile, offset, os2method, &newoffset);
562 if(rc)
563 {
564 SetLastError(error2WinError(rc));
565 return -1;
566 }
567 else return newoffset;
568}
569//******************************************************************************
570//******************************************************************************
571BOOL OSLibDosDelete(char *lpszFileName)
572{
573 APIRET rc;
574
575 rc = DosDelete(lpszFileName);
576 if(rc) {
577 SetLastError(error2WinError(rc));
578 return FALSE;
579 }
580 return TRUE;
581}
582//******************************************************************************
583//******************************************************************************
584BOOL pmDateTimeToFileTime(FDATE *pDate,FTIME *pTime,FILETIME *pFT)
585{
586 register USHORT dosTime, dosDate;
587
588 dosTime = *(USHORT*)pTime;
589 dosDate = *(USHORT*)pDate;
590
591 // PH: probably replace with faster implementation than calling Open32
592 // through the external interface!
593 return DosDateTimeToFileTime(dosDate,dosTime,pFT);
594}
595//******************************************************************************
596//******************************************************************************
597#define NOT_NORMAL (FILE_ATTRIBUTE_READONLY_W | \
598 FILE_ATTRIBUTE_HIDDEN_W | \
599 FILE_ATTRIBUTE_SYSTEM_W | \
600 FILE_ATTRIBUTE_ARCHIVE_W)
601
602inline DWORD pm2WinFileAttributes(DWORD attrFile)
603{
604 DWORD res = 0;
605
606 if (!(attrFile & NOT_NORMAL))
607 res |= FILE_ATTRIBUTE_NORMAL_W;
608 if (attrFile & FILE_READONLY)
609 res |= FILE_ATTRIBUTE_READONLY_W;
610 if (attrFile & FILE_HIDDEN)
611 res |= FILE_ATTRIBUTE_HIDDEN_W;
612 if (attrFile & FILE_SYSTEM)
613 res |= FILE_ATTRIBUTE_SYSTEM_W;
614 if (attrFile & FILE_DIRECTORY)
615 res |= FILE_ATTRIBUTE_DIRECTORY_W;
616 if (attrFile & FILE_ARCHIVED)
617 res |= FILE_ATTRIBUTE_ARCHIVE_W;
618
619 //CB: not used: FILE_ATTRIBUTE_COMPRESSED_W
620 //PH: NT server will serve appropriate sizes for compressed files
621 // over network. So if realSize < allocatedSize, the file must
622 // be compressed.
623
624 return res;
625}
626//******************************************************************************
627//******************************************************************************
628BOOL OSLibDosGetFileAttributesEx(PSZ pszName,
629 ULONG ulDummy,
630 PVOID pBuffer)
631{
632 APIRET rc; /* API return code */
633 FILESTATUS3 fs3; /* file information structure */
634 LPWIN32_FILE_ATTRIBUTE_DATA lpFad = (LPWIN32_FILE_ATTRIBUTE_DATA) pBuffer;
635
636 // Note: we only handle standard "GetFileExInfoStandard" requests
637 rc = DosQueryPathInfo(pszName, /* query the file information */
638 FIL_STANDARD,
639 &fs3,
640 sizeof(fs3));
641 if (rc != NO_ERROR) /* check for errors */
642 return FALSE; /* raise error condition */
643
644 // convert structure
645 lpFad->dwFileAttributes = pm2WinFileAttributes(fs3.attrFile);
646 pmDateTimeToFileTime(&fs3.fdateCreation, &fs3.ftimeCreation, &lpFad->ftCreationTime);
647 pmDateTimeToFileTime(&fs3.fdateLastAccess, &fs3.ftimeLastAccess, &lpFad->ftLastAccessTime);
648 pmDateTimeToFileTime(&fs3.fdateLastWrite, &fs3.ftimeLastWrite, &lpFad->ftLastWriteTime);
649
650 /* @@@PH we might add Aurora support ...
651 lpFad->nFileSizeHigh = info.nFileSizeHigh;
652 */
653 lpFad->nFileSizeHigh = 0;
654 lpFad->nFileSizeLow = fs3.cbFile;
655
656 return TRUE;
657}
658//******************************************************************************
659DWORD WIN32API GetEnvironmentVariableA(LPCSTR, LPSTR, DWORD );
660//******************************************************************************
661DWORD OSLibDosSearchPath(DWORD cmd, char *path, char *name, char *full_name,
662 DWORD length_fullname)
663{
664 switch(cmd) {
665 case OSLIB_SEARCHDIR:
666 if(DosSearchPath(SEARCH_IGNORENETERRS, path,
667 name, full_name, length_fullname) != 0) {
668 return 0;
669 }
670 return strlen(full_name);
671
672
673 case OSLIB_SEARCHCURDIR:
674 if(DosSearchPath(SEARCH_IGNORENETERRS | SEARCH_CUR_DIRECTORY, path,
675 name, full_name, length_fullname) != 0) {
676 return 0;
677 }
678 return strlen(full_name);
679
680 case OSLIB_SEARCHFILE:
681 {
682 FILESTATUS3 fileinfo;
683
684 if(DosQueryPathInfo(name, FIL_STANDARD, &fileinfo, sizeof(fileinfo)) != 0) {
685 return 0;
686 }
687 strncpy(full_name, name, length_fullname);
688 full_name[length_fullname-1] = 0;
689 return strlen(full_name);
690 }
691
692 case OSLIB_SEARCHENV:
693 {
694 LPSTR envstring;
695 int envsize;
696 CHAR szResult[CCHMAXPATH];
697
698 envsize = GetEnvironmentVariableA(path, NULL, 0);
699 envstring = (LPSTR)malloc(envsize+1);
700 GetEnvironmentVariableA(path, envstring, envsize);
701 if(DosSearchPath(SEARCH_IGNORENETERRS, envstring,
702 name, szResult, sizeof(szResult)) != 0) {
703 free(envstring);
704 return 0;
705 }
706 free(envstring);
707 strcpy(full_name, szResult);
708 return strlen(full_name);
709 }
710 }
711 return 0;
712}
713//******************************************************************************
714//******************************************************************************
715DWORD OSLibDosQueryPathInfo(CHAR *pszPathName,
716 ULONG ulInfoLevel,
717 PVOID pInfoBuf,
718 ULONG cbInfoBuf)
719{
720 APIRET rc = DosQueryPathInfo( pszPathName, ulInfoLevel,
721 pInfoBuf, cbInfoBuf );
722
723 if(rc == ERROR_TOO_MANY_OPEN_FILES)
724 {
725 LONG reqCount = 2;
726 ULONG maxFiles;
727
728 if(DosSetRelMaxFH(&reqCount, &maxFiles) == NO_ERROR)
729 rc = DosQueryPathInfo(pszPathName, ulInfoLevel,
730 pInfoBuf, cbInfoBuf );
731 }
732 return rc;
733}
734//******************************************************************************
735//******************************************************************************
736DWORD OSLibDosCreateFile(CHAR *lpszFile,
737 DWORD fuAccess,
738 DWORD fuShare,
739 LPSECURITY_ATTRIBUTES lpSecurityAttributes,
740 DWORD fuCreate,
741 DWORD fuAttrFlags,
742 HANDLE hTemplateFile)
743{
744 HFILE hFile;
745 ULONG actionTaken = 0;
746 ULONG fileSize = 0;
747 ULONG fileAttr = FILE_NORMAL;
748 ULONG openFlag = 0;
749 ULONG openMode = 0;
750 APIRET rc = ERROR_NOT_ENOUGH_MEMORY;;
751
752 //TODO: lpSecurityAttributes (inheritance)
753
754 if(fuAttrFlags & FILE_ATTRIBUTE_ARCHIVE_W)
755 fileAttr |= FILE_ARCHIVED;
756 if(fuAttrFlags & FILE_ATTRIBUTE_HIDDEN_W)
757 fileAttr |= FILE_HIDDEN;
758 if(fuAttrFlags & FILE_ATTRIBUTE_SYSTEM_W)
759 fileAttr |= FILE_SYSTEM;
760 if(fuAttrFlags & FILE_ATTRIBUTE_READONLY_W)
761 fileAttr |= FILE_READONLY;
762 // TODO: FILE_ATTRIBUTE_TEMPORARY_W
763
764 switch(fuCreate)
765 {
766 case CREATE_NEW_W:
767 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_FAIL_IF_EXISTS;
768 break;
769 case CREATE_ALWAYS_W:
770 /* kso 2000-11-26: Not sure if OPEN_ACTION_REPLACE_IF_EXISTS is correct here! It is correct according to
771 * MSDN, but not according to "The Win32 API SuperBible". Anyway I haven't got time to check it out in
772 * NT now.
773 * The problem is that OPEN_ACTION_REPLACE_IF_EXISTS requires write access. It failes with
774 * rc = ERROR_ACCESS_DENIED (5). Quick fix, use OPEN_IF_EXIST if readonly access.
775 */
776 if (fuAccess & GENERIC_WRITE_W)
777 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS;
778 else
779 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
780 break;
781 case OPEN_EXISTING_W:
782 openFlag |= OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
783 break;
784 case OPEN_ALWAYS_W:
785 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
786 break;
787 case TRUNCATE_EXISTING_W:
788 openFlag |= OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS;
789 break;
790 }
791
792 if(fuAttrFlags & FILE_FLAG_WRITE_THROUGH_W) openMode |= OPEN_FLAGS_WRITE_THROUGH;
793 if(fuAttrFlags & FILE_FLAG_NO_BUFFERING_W) openMode |= OPEN_FLAGS_NO_CACHE;
794 if(fuAttrFlags & FILE_FLAG_RANDOM_ACCESS_W) openMode |= OPEN_FLAGS_RANDOM;
795 if(fuAttrFlags & FILE_FLAG_SEQUENTIAL_SCAN_W) openMode |= OPEN_FLAGS_SEQUENTIAL;
796 // TODO: FILE_FLAG_BACKUP_SEMANTICS_W
797 // FILE_FLAG_POSIX_SEMANTICS_W are not supported
798
799 //TODO: FILE_SHARE_DELETE
800 if((fuShare & (FILE_SHARE_READ_W | FILE_SHARE_WRITE_W)) == 0 )
801 openMode |= OPEN_SHARE_DENYREADWRITE;
802 else
803 if((fuShare & (FILE_SHARE_READ_W | FILE_SHARE_WRITE_W)) == (FILE_SHARE_READ_W | FILE_SHARE_WRITE_W))
804 openMode |= OPEN_SHARE_DENYNONE;
805 else
806 if(fuShare & FILE_SHARE_READ_W)
807 openMode |= OPEN_SHARE_DENYWRITE;
808 else
809 if(fuShare & FILE_SHARE_WRITE_W)
810 openMode |= OPEN_SHARE_DENYREAD;
811
812 if(fuAccess == (GENERIC_READ_W | GENERIC_WRITE_W))
813 openMode |= OPEN_ACCESS_READWRITE;
814 else
815 if(fuAccess & GENERIC_READ_W)
816 openMode |= OPEN_ACCESS_READONLY;
817 else
818 if(fuAccess & GENERIC_WRITE_W)
819 openMode |= OPEN_ACCESS_WRITEONLY;
820
821#if 0
822 //SvL: Not true; verified in NT! (also messed up access of files on
823 // readonly volumes)
824 // CreateFile with OPEN_ALWAYS & GENERIC_READ on non-existing file
825 // -> creates 0 size file, WriteFile is not allowed
826 // Same in OS/2.
827 /* if creating a file, access cannot be readonly! */
828 if (openFlag & OPEN_ACTION_CREATE_IF_NEW &&
829 (!(openMode & OPEN_ACCESS_READWRITE) &&
830 !(openMode & OPEN_ACCESS_WRITEONLY))) {
831 openMode |= OPEN_ACCESS_READWRITE;
832 }
833#endif
834
835 if(strlen(lpszFile) == 2 && lpszFile[1] == ':') {
836 //app tries to open physical disk
837 openMode |= OPEN_FLAGS_DASD;
838 }
839 int retry = 0;
840 while (retry < 3)
841 {
842 dprintf(("DosOpen %s openFlag=%x openMode=%x", lpszFile, openFlag, openMode));
843 rc = DosOpen((PSZ)lpszFile,
844 &hFile,
845 &actionTaken,
846 fileSize,
847 fileAttr,
848 openFlag,
849 openMode,
850 NULL);
851 if (rc == ERROR_TOO_MANY_OPEN_FILES)
852 {
853 ULONG CurMaxFH;
854 LONG ReqCount = 32;
855
856 rc = DosSetRelMaxFH(&ReqCount, &CurMaxFH);
857 if(rc) {
858 dprintf(("DosSetRelMaxFH returned %d", rc));
859 SetLastError(ERROR_TOO_MANY_OPEN_FILES_W);
860 return INVALID_HANDLE_VALUE_W;
861 }
862 dprintf(("DosOpen failed -> increased nr open files to %d", CurMaxFH));
863 }
864 #if 0
865 else if (rc == ERROR_ACCESS_DENIED && (openFlag & OPEN_ACTION_REPLACE_IF_EXISTS))
866 { /* kso: I have great problems with the REPLACE not working
867 * So, I guess this emulation may help...
868 * This problem exist on WS4eB SMP FP1 and Warp4 FP14/Kernel 14059 at least.
869 */
870 rc = DosOpen((PSZ)lpszFile,
871 &hFile,
872 &actionTaken,
873 fileSize,
874 fileAttr,
875 (openFlag & ~OPEN_ACTION_REPLACE_IF_EXISTS) | OPEN_ACTION_OPEN_IF_EXISTS,
876 openMode,
877 NULL);
878 if (rc == NO_ERROR)
879 {
880 rc = DosSetFileSize(hFile, 0);
881 if (!rc && fileSize > 0)
882 rc = DosSetFileSize(hFile, fileSize);
883 if (rc)
884 {
885 DosClose(hFile);
886 hFile = NULLHANDLE;
887
888 if (rc != ERROR_TOO_MANY_OPEN_FILES)
889 break;
890 }
891 else break;
892 }
893 }
894 #endif
895 else break;
896 retry++;
897 }
898
899 if(rc)
900 {
901 SetLastError(error2WinError(rc));
902 return INVALID_HANDLE_VALUE_W;
903 }
904 SetLastError(ERROR_SUCCESS_W);
905 return hFile;
906}
907//******************************************************************************
908//******************************************************************************
909DWORD OSLibDosOpenFile(CHAR *lpszFile, UINT fuMode)
910{
911 ULONG actionTaken = 0;
912 ULONG fileSize = 0;
913 ULONG fileAttr = FILE_NORMAL;
914 ULONG openFlag = 0;
915 ULONG openMode = 0;
916 APIRET rc = ERROR_NOT_ENOUGH_MEMORY;
917 HFILE hFile;
918
919 if(!(fuMode & (OF_CREATE_W | OF_READWRITE_W | OF_WRITE_W)))
920 {
921 openMode |= OPEN_ACCESS_READONLY;
922 openFlag |= OPEN_ACTION_OPEN_IF_EXISTS;
923 }
924 else
925 {
926 if(fuMode & OF_CREATE_W) {
927 openFlag |= OPEN_ACTION_CREATE_IF_NEW |
928 OPEN_ACTION_REPLACE_IF_EXISTS;
929 }
930 else openFlag |= OPEN_ACTION_OPEN_IF_EXISTS;
931
932 if(fuMode & OF_READWRITE_W)
933 openMode |= OPEN_ACCESS_READWRITE;
934 else
935 if(fuMode & OF_WRITE_W)
936 openMode |= OPEN_ACCESS_WRITEONLY;
937 else
938 if(fuMode & OF_CREATE_W)
939 openMode |= OPEN_ACCESS_READWRITE;
940 }
941
942 if((fuMode & OF_SHARE_DENY_WRITE_W) ||
943 !(fuMode & (OF_SHARE_DENY_READ_W | OF_SHARE_DENY_NONE_W | OF_SHARE_EXCLUSIVE_W)))
944 openMode |= OPEN_SHARE_DENYWRITE;
945 else
946 if (fuMode & OF_SHARE_DENY_NONE_W)
947 openMode |= OPEN_SHARE_DENYNONE;
948 else
949 if (fuMode & OF_SHARE_DENY_READ_W)
950 openMode |= OPEN_SHARE_DENYREAD;
951 else
952 if (fuMode & OF_SHARE_EXCLUSIVE_W)
953 openMode |= OPEN_SHARE_DENYREADWRITE;
954
955 rc = DosOpen((PSZ)lpszFile,
956 &hFile,
957 &actionTaken,
958 fileSize,
959 fileAttr,
960 openFlag,
961 openMode,
962 NULL);
963
964 if(rc != NO_ERROR)
965 {
966 if(fuMode & OF_EXIST_W)
967 {
968 if(rc == ERROR_OPEN_FAILED || rc == ERROR_FILE_NOT_FOUND)
969 {
970 SetLastError(ERROR_FILE_NOT_FOUND_W);
971 return HFILE_ERROR_W;
972 }
973 }
974 if((rc == ERROR_OPEN_FAILED) && (openFlag & OPEN_ACTION_OPEN_IF_EXISTS))
975 {
976 SetLastError(ERROR_FILE_NOT_FOUND_W);
977 }
978 else SetLastError(error2WinError(rc));
979
980 return HFILE_ERROR_W;
981 }
982 SetLastError(ERROR_SUCCESS_W);
983 return hFile;
984}
985//******************************************************************************
986//******************************************************************************
987BOOL OSLibDosLockFile(DWORD hFile, DWORD dwFlags,
988 DWORD OffsetLow, DWORD OffsetHigh,
989 DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh,
990 LPOVERLAPPED lpOverlapped)
991{
992 APIRET rc;
993
994 // Set 5 secs timeout for locking file and no other can access this
995 // file region
996
997 if(lpOverlapped) {//TODO:
998 dprintf(("OSLibDosLockFile: overlapped lock not yet implemented!!"));
999 }
1000 //TODO: Locking region crossing end of file is permitted. Works in OS/2??
1001 if(f64BitIO)
1002 {
1003 FILELOCKL lockRangeL;
1004
1005 lockRangeL.lOffset.ulLo = OffsetLow;
1006 lockRangeL.lOffset.ulHi = OffsetHigh;
1007 lockRangeL.lRange.ulLo = nNumberOfBytesToLockLow;
1008 lockRangeL.lRange.ulHi = nNumberOfBytesToLockHigh;
1009
1010 rc = OdinDosSetFileLocksL(hFile, NULL, &lockRangeL,
1011 (dwFlags & LOCKFILE_FAIL_IMMEDIATELY_W) ? 0 : 5000, 0);
1012 //SvL: 64 bits values are only supported by JFS
1013 // Try the 32 bits DosSetFileLocks if it fails
1014 // (TODO: should check the partition type instead)
1015 if(rc == ERROR_INVALID_PARAMETER && (OffsetHigh || nNumberOfBytesToLockHigh)) {
1016 goto oldlock;
1017 }
1018 }
1019 else
1020 {
1021oldlock:
1022 FILELOCK lockRange = { OffsetLow, nNumberOfBytesToLockLow };
1023
1024 rc = DosSetFileLocks(hFile, NULL, &lockRange,
1025 (dwFlags & LOCKFILE_FAIL_IMMEDIATELY_W) ? 0 : 5000, 0);
1026 }
1027 if(rc) {
1028 SetLastError(error2WinError(rc));
1029 return FALSE;
1030 }
1031 SetLastError(ERROR_SUCCESS_W);
1032 return TRUE;
1033}
1034//******************************************************************************
1035//******************************************************************************
1036BOOL OSLibDosUnlockFile(DWORD hFile, DWORD OffsetLow, DWORD OffsetHigh,
1037 DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh,
1038 LPOVERLAPPED lpOverlapped)
1039{
1040 APIRET rc;
1041
1042 // Set 5 secs timeout for unlocking file and no other can access this
1043 // file region
1044
1045 if(lpOverlapped) {//TODO:
1046 dprintf(("OSLibDosUnlockFile: overlapped unlock not yet implemented!!"));
1047 }
1048 if(f64BitIO)
1049 {
1050 FILELOCKL unlockRangeL;
1051
1052 unlockRangeL.lOffset.ulLo = OffsetLow;
1053 unlockRangeL.lOffset.ulHi = OffsetHigh;
1054 unlockRangeL.lRange.ulLo = nNumberOfBytesToLockLow;
1055 unlockRangeL.lRange.ulHi = nNumberOfBytesToLockHigh;
1056
1057 rc = OdinDosSetFileLocksL(hFile, &unlockRangeL, NULL, 5000, 0);
1058 //SvL: 64 bits values are only supported by JFS
1059 // Try the 32 bits DosSetFileLocks if it fails
1060 // (TODO: should check the partition type instead)
1061 if(rc == ERROR_INVALID_PARAMETER && (OffsetHigh || nNumberOfBytesToLockHigh)) {
1062 goto oldlock;
1063 }
1064 }
1065 else
1066 {
1067oldlock:
1068 FILELOCK unlockRange = { OffsetLow, nNumberOfBytesToLockLow };
1069
1070 rc = DosSetFileLocks(hFile, &unlockRange, NULL, 5000, 0);
1071 }
1072 if(rc) {
1073 SetLastError(error2WinError(rc));
1074 return FALSE;
1075 }
1076 SetLastError(ERROR_SUCCESS_W);
1077 return TRUE;
1078}
1079//******************************************************************************
1080//******************************************************************************
1081BOOL OSLibDosFlushFileBuffers(DWORD hFile)
1082{
1083 APIRET rc;
1084
1085 rc = DosResetBuffer(hFile);
1086 SetLastError(error2WinError(rc));
1087 return (rc == NO_ERROR);
1088}
1089//******************************************************************************
1090//******************************************************************************
1091DWORD OSLibDosGetFileSize(DWORD hFile, LPDWORD lpdwFileSizeHigh)
1092{
1093 APIRET rc;
1094 ULONG sizeLow;
1095
1096 if(f64BitIO)
1097 {
1098 FILESTATUS3L fsts3ConfigInfoL = {{0}};
1099 ULONG ulBufSize = sizeof(FILESTATUS3L);
1100
1101 rc = DosQueryFileInfo(hFile, FIL_STANDARDL, &fsts3ConfigInfoL, ulBufSize);
1102 if(lpdwFileSizeHigh) {
1103 *lpdwFileSizeHigh = fsts3ConfigInfoL.cbFile.ulHi;
1104 }
1105 sizeLow = fsts3ConfigInfoL.cbFile.ulLo;
1106 }
1107 else
1108 {
1109 FILESTATUS3 fsts3ConfigInfo = {{0}};
1110 ULONG ulBufSize = sizeof(FILESTATUS3);
1111
1112 if(lpdwFileSizeHigh) {
1113 *lpdwFileSizeHigh = 0;
1114 }
1115 rc = DosQueryFileInfo(hFile, FIL_STANDARD, &fsts3ConfigInfo, ulBufSize);
1116 sizeLow = fsts3ConfigInfo.cbFile;
1117 }
1118 if(rc) {
1119 SetLastError(error2WinError(rc));
1120 return -1;
1121 }
1122 SetLastError(ERROR_SUCCESS_W);
1123 return sizeLow;
1124}
1125//******************************************************************************
1126//******************************************************************************
1127DWORD OSLibDosSetFilePointer(DWORD hFile, DWORD OffsetLow, DWORD *OffsetHigh, DWORD method)
1128{
1129 LONGLONG offsetL;
1130 LONGLONG newoffsetL;
1131 APIRET rc;
1132 DWORD newoffset;
1133
1134 switch(method)
1135 {
1136 case FILE_BEGIN_W:
1137 method = FILE_BEGIN;
1138 break;
1139
1140 case FILE_CURRENT_W:
1141 method = FILE_CURRENT;
1142 break;
1143
1144 case FILE_END_W:
1145 method = FILE_END;
1146 break;
1147 }
1148
1149 // PH Note: for a negative 32-bit seek, the OS/2 64-bit version
1150 // needs to be skipped.
1151 if( (f64BitIO) && (OffsetHigh) )
1152 {
1153 offsetL.ulLo = OffsetLow;
1154 offsetL.ulHi = (OffsetHigh) ? *OffsetHigh : 0;
1155 rc = OdinDosSetFilePtrL(hFile, offsetL, method, &newoffsetL);
1156 if(OffsetHigh) {
1157 *OffsetHigh = newoffsetL.ulHi;
1158 }
1159 newoffset = newoffsetL.ulLo;
1160 }
1161 else rc = DosSetFilePtr(hFile, OffsetLow, method, &newoffset);
1162
1163 if(rc)
1164 {
1165 SetLastError(error2WinError(rc));
1166 return -1;
1167 }
1168 SetLastError(ERROR_SUCCESS_W);
1169 return newoffset;
1170}
1171//******************************************************************************
1172//******************************************************************************
1173BOOL OSLibDosSetEndOfFile(DWORD hFile)
1174{
1175 ULONG newFilePos;
1176 LONGLONG FilePosL = {0,0};
1177 LONGLONG newFilePosL;
1178 APIRET rc;
1179
1180 if(f64BitIO) {
1181 rc = OdinDosSetFilePtrL(hFile, FilePosL, FILE_CURRENT, &newFilePosL);
1182 if(rc == 0) {
1183 rc = OdinDosSetFileSizeL(hFile, newFilePosL);
1184 }
1185 }
1186 else {
1187 rc = DosSetFilePtr(hFile, 0, FILE_CURRENT, &newFilePos);
1188 if(rc == 0) {
1189 rc = DosSetFileSize(hFile, newFilePos);
1190 }
1191 }
1192 if(rc) {
1193 SetLastError(error2WinError(rc));
1194 return FALSE;
1195 }
1196 SetLastError(ERROR_SUCCESS_W);
1197 return TRUE;
1198}
1199//******************************************************************************
1200//******************************************************************************
1201BOOL OSLibDosGetFileInformationByHandle(DWORD hFile, BY_HANDLE_FILE_INFORMATION* pInfo)
1202{
1203 APIRET rc;
1204
1205 if(f64BitIO)
1206 {
1207 FILESTATUS4L statusL = { 0 };
1208
1209 rc = DosQueryFileInfo(hFile, FIL_QUERYEASIZEL,
1210 &statusL, sizeof(statusL));
1211 if(rc == NO_ERROR)
1212 {
1213 pInfo->dwFileAttributes = 0;
1214 if(!(statusL.attrFile & NOT_NORMAL))
1215 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_NORMAL_W;
1216 if(statusL.attrFile & FILE_READONLY)
1217 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_READONLY_W;
1218 if(statusL.attrFile & FILE_HIDDEN)
1219 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN_W;
1220 if(statusL.attrFile & FILE_SYSTEM)
1221 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_SYSTEM_W;
1222 if(statusL.attrFile & FILE_DIRECTORY)
1223 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY_W;
1224 if(statusL.attrFile & FILE_ARCHIVED)
1225 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_ARCHIVE_W;
1226
1227 pmDateTimeToFileTime(&statusL.fdateCreation,
1228 &statusL.ftimeCreation,
1229 &pInfo->ftCreationTime);
1230 pmDateTimeToFileTime(&statusL.fdateLastAccess,
1231 &statusL.ftimeLastAccess,
1232 &pInfo->ftLastAccessTime);
1233 pmDateTimeToFileTime(&statusL.fdateLastWrite,
1234 &statusL.ftimeLastWrite,
1235 &pInfo->ftLastWriteTime);
1236
1237 pInfo->nFileSizeHigh = statusL.cbFile.ulHi;
1238 pInfo->nFileSizeLow = statusL.cbFile.ulLo;
1239 pInfo->dwVolumeSerialNumber = 0; //todo
1240 pInfo->nNumberOfLinks = 1;
1241 pInfo->nFileIndexHigh = 0;
1242 pInfo->nFileIndexLow = 0;
1243 }
1244 }
1245 else
1246 {
1247 FILESTATUS4 status = { 0 };
1248
1249 rc = DosQueryFileInfo(hFile, FIL_QUERYEASIZE, &status,
1250 sizeof(status));
1251 if(rc == NO_ERROR)
1252 {
1253 pInfo->dwFileAttributes = 0;
1254 if(!(status.attrFile & NOT_NORMAL))
1255 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_NORMAL_W;
1256 if(status.attrFile & FILE_READONLY)
1257 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_READONLY_W;
1258 if(status.attrFile & FILE_HIDDEN)
1259 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN_W;
1260 if(status.attrFile & FILE_SYSTEM)
1261 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_SYSTEM_W;
1262 if(status.attrFile & FILE_DIRECTORY)
1263 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY_W;
1264 if(status.attrFile & FILE_ARCHIVED)
1265 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_ARCHIVE_W;
1266
1267 pmDateTimeToFileTime(&status.fdateCreation,
1268 &status.ftimeCreation,
1269 &pInfo->ftCreationTime);
1270 pmDateTimeToFileTime(&status.fdateLastAccess,
1271 &status.ftimeLastAccess,
1272 &pInfo->ftLastAccessTime);
1273 pmDateTimeToFileTime(&status.fdateLastWrite,
1274 &status.ftimeLastWrite,
1275 &pInfo->ftLastWriteTime);
1276
1277 pInfo->nFileSizeHigh = 0;
1278 pInfo->nFileSizeLow = status.cbFile;
1279 pInfo->dwVolumeSerialNumber = 0; //todo
1280 pInfo->nNumberOfLinks = 1;
1281 pInfo->nFileIndexHigh = 0;
1282 pInfo->nFileIndexLow = 0;
1283 }
1284 }
1285 if(rc) {
1286 SetLastError(error2WinError(rc));
1287 return FALSE;
1288 }
1289 SetLastError(ERROR_SUCCESS_W);
1290 return TRUE;
1291}
1292//******************************************************************************
1293//******************************************************************************
1294BOOL OSLibDosSetFileTime(DWORD hFile, WORD creationdate, WORD creationtime,
1295 WORD lastaccessdate, WORD lastaccesstime,
1296 WORD lastwritedate, WORD lastwritetime)
1297{
1298 FILESTATUS3 fileInfo;
1299 APIRET rc;
1300
1301 rc = DosQueryFileInfo(hFile, FIL_STANDARD, &fileInfo, sizeof(fileInfo));
1302
1303 if(rc == NO_ERROR)
1304 {
1305 if(creationdate && creationtime) {
1306 fileInfo.fdateCreation = *(FDATE *)&creationdate;
1307 fileInfo.ftimeCreation = *(FTIME *)&creationtime;
1308 }
1309 if(lastaccessdate && lastaccesstime) {
1310 fileInfo.fdateLastAccess = *(FDATE *)&lastaccessdate;
1311 fileInfo.ftimeLastAccess = *(FTIME *)&lastaccesstime;
1312 }
1313 if(lastwritedate && lastwritetime) {
1314 fileInfo.fdateLastWrite = *(FDATE *)&lastwritedate;
1315 fileInfo.ftimeLastWrite = *(FTIME *)&lastwritetime;
1316 }
1317
1318 rc = DosSetFileInfo(hFile, FIL_STANDARD, &fileInfo, sizeof(fileInfo));
1319 }
1320
1321 if(rc)
1322 {
1323 SetLastError(error2WinError(rc));
1324 return FALSE;
1325 }
1326 SetLastError(ERROR_SUCCESS_W);
1327 return TRUE;
1328}
1329//******************************************************************************
1330//******************************************************************************
1331BOOL OSLibDosGetFileTime(DWORD hFile, WORD *creationdate, WORD *creationtime,
1332 WORD *lastaccessdate, WORD *lastaccesstime,
1333 WORD *lastwritedate, WORD *lastwritetime)
1334{
1335 FILESTATUS3 fileInfo;
1336 APIRET rc;
1337
1338 rc = DosQueryFileInfo(hFile, FIL_STANDARD, &fileInfo, sizeof(fileInfo));
1339
1340 if(rc == NO_ERROR)
1341 {
1342 *creationdate = *(WORD *)&fileInfo.fdateCreation;
1343 *creationtime = *(WORD *)&fileInfo.ftimeCreation;
1344 *lastaccessdate = *(WORD *)&fileInfo.fdateLastAccess;
1345 *lastaccesstime = *(WORD *)&fileInfo.ftimeLastAccess;
1346 *lastwritedate = *(WORD *)&fileInfo.fdateLastWrite;
1347 *lastwritetime = *(WORD *)&fileInfo.ftimeLastWrite;
1348 }
1349
1350 if(rc)
1351 {
1352 SetLastError(error2WinError(rc));
1353 return FALSE;
1354 }
1355 SetLastError(ERROR_SUCCESS_W);
1356 return TRUE;
1357}
1358//******************************************************************************
1359//******************************************************************************
1360DWORD OSLibDosSetFilePtr2(DWORD hFile, DWORD offset, DWORD method)
1361{
1362 DWORD newoffset;
1363 APIRET rc;
1364
1365
1366 rc = DosSetFilePtr(hFile, offset, method, &newoffset);
1367 if(rc) {
1368 dprintf(("DosSetFilePtr Error rc:%d", rc));
1369 return -1;
1370 }
1371 else return newoffset;
1372}
1373//******************************************************************************
1374//******************************************************************************
1375DWORD OSLibDosDupHandle(DWORD hFile, DWORD *hNew)
1376{
1377 *hNew = -1;
1378 return DosDupHandle(hFile, hNew);
1379}
1380//******************************************************************************
1381//******************************************************************************
1382void OSLibDosDisableHardError(BOOL fTurnOff)
1383{
1384 DosError((fTurnOff) ? FERR_DISABLEHARDERR : FERR_ENABLEHARDERR);
1385}
1386//******************************************************************************
1387//Returns time spent in kernel & user mode in milliseconds
1388//******************************************************************************
1389BOOL OSLibDosQueryProcTimes(DWORD procid, ULONG *kerneltime, ULONG *usertime)
1390{
1391 APIRET rc;
1392 char *buf;
1393 ULONG size;
1394 ULONG nrthreads = 4;
1395
1396tryagain:
1397 size = sizeof(QTOPLEVEL)+sizeof(QGLOBAL)+sizeof(QPROCESS) + nrthreads*sizeof(QTHREAD);
1398 buf = (char *)malloc(size);
1399 rc = DosQuerySysState(0x1, RESERVED, procid, RESERVED, (PCHAR)buf, size);
1400
1401 if(rc) {
1402 free(buf);
1403 if(rc == ERROR_BUFFER_OVERFLOW) {
1404 nrthreads += 4;
1405 goto tryagain;
1406 }
1407 return FALSE;
1408 }
1409 PQTOPLEVEL top = (PQTOPLEVEL)buf;
1410
1411 *kerneltime = 0;
1412 *usertime = 0;
1413 for(int i=0;i<top->procdata->threadcnt;i++) {
1414 *kerneltime += top->procdata->threads[i].systime;
1415 *usertime += top->procdata->threads[i].usertime;
1416 }
1417 free(buf);
1418 return TRUE;
1419}
1420//******************************************************************************
1421//******************************************************************************
1422// TODO: implement SecurityAttributes parameter
1423DWORD OSLibDosCreateNamedPipe(LPCTSTR lpName,
1424 DWORD dwOpenMode,
1425 DWORD dwPipeMode,
1426 DWORD nMaxInstances,
1427 DWORD nOutBufferSize,
1428 DWORD nInBufferSize,
1429 DWORD nDefaultTimeOut,
1430 LPSECURITY_ATTRIBUTES lpSecurityAttributes)
1431{ DWORD dwOS2Mode = 0;
1432 DWORD dwOS2PipeMode = 0;
1433 LPSTR lpOS2Name;
1434 DWORD hPipe;
1435 DWORD rc;
1436
1437 if (dwOpenMode & PIPE_ACCESS_DUPLEX_W)
1438 dwOS2Mode |= NP_ACCESS_DUPLEX;
1439 else
1440 if (dwOpenMode & PIPE_ACCESS_INBOUND_W)
1441 dwOS2Mode |= NP_ACCESS_INBOUND;
1442 else
1443 if (dwOpenMode & PIPE_ACCESS_OUTBOUND_W)
1444 dwOS2Mode |= NP_ACCESS_OUTBOUND;
1445 // TODO:
1446 // if(dwOpenMode & FILE_FLAG_OVERLAPPED)
1447 // if(dwOpenMode & WRITE_DAC)
1448 // if(dwOpenMode & WRITE_OWNER)
1449 // if(dwOpenMode & ACCESS_SYSTEM_SECURITY)
1450 if(dwOpenMode & FILE_FLAG_WRITE_THROUGH_W)
1451 dwOS2Mode |= NP_WRITEBEHIND; // FIXME: I'm not sure!
1452
1453 if (dwPipeMode & PIPE_WAIT_W)
1454 dwOS2PipeMode |= NP_WAIT;
1455 if (dwPipeMode & PIPE_NOWAIT_W)
1456 dwOS2PipeMode |= NP_NOWAIT;
1457 if (dwPipeMode & PIPE_READMODE_BYTE_W)
1458 dwOS2PipeMode |= NP_READMODE_BYTE;
1459 if (dwPipeMode & PIPE_READMODE_MESSAGE_W)
1460 dwOS2PipeMode |= NP_READMODE_MESSAGE;
1461 if (dwPipeMode & PIPE_TYPE_BYTE_W)
1462 dwOS2PipeMode |= NP_TYPE_BYTE;
1463 if (dwPipeMode & PIPE_TYPE_MESSAGE_W)
1464 dwOS2PipeMode |= NP_TYPE_MESSAGE;
1465
1466 if (nMaxInstances>0xff)
1467 {
1468 SetLastError(ERROR_INVALID_PARAMETER_W); // ERROR_INVALID_PARAMETER
1469 return -1; // INVALID_HANDLE_VALUE
1470 }
1471 dwOS2PipeMode |= nMaxInstances;
1472
1473 if (strstr(lpName,"\\\\."))
1474 {
1475 // If pipe is created on the local machine
1476 // we must delete string \\. because
1477 // in Windows named pipes scheme is a \\.\PIPE\pipename
1478 // but in OS/2 only \PIPE\pipename
1479 lpOS2Name = (LPSTR)lpName + 3;
1480 }
1481 else lpOS2Name = (LPSTR)lpName;
1482
1483 dprintf(("DosCreateNPipe(%s,%x,%x,%x,%x,%x)",lpOS2Name,dwOS2Mode,dwOS2PipeMode,nInBufferSize,nOutBufferSize,nDefaultTimeOut));
1484 rc=DosCreateNPipe(lpOS2Name,
1485 &hPipe,
1486 dwOS2Mode,
1487 dwOS2PipeMode,
1488 nInBufferSize,
1489 nInBufferSize,
1490 nDefaultTimeOut); // Timeouts must be tested!
1491
1492 dprintf(("DosCreateNPipe rc=%d",rc));
1493 if (rc)
1494 {
1495 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER_W));
1496 return -1; // INVALID_HANDLE_VALUE
1497 }
1498 return hPipe;
1499}
1500
1501//******************************************************************************
1502//******************************************************************************
1503// TODO: implement lpOverlapped parameter!
1504BOOL OSLibDosConnectNamedPipe(DWORD hNamedPipe, LPOVERLAPPED lpOverlapped)
1505{
1506 DWORD rc;
1507
1508 rc=DosConnectNPipe(hNamedPipe);
1509 dprintf(("DosConnectNPipe rc=%d",rc));
1510
1511 if (!rc) return (TRUE);
1512 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1513
1514 return (FALSE);
1515}
1516
1517//******************************************************************************
1518//******************************************************************************
1519BOOL OSLibDosCallNamedPipe( LPCTSTR lpNamedPipeName,
1520 LPVOID lpInBuffer,
1521 DWORD nInBufferSize,
1522 LPVOID lpOutBuffer,
1523 DWORD nOutBufferSize,
1524 LPDWORD lpBytesRead,
1525 DWORD nTimeOut )
1526{
1527 LPSTR lpOS2Name;
1528 DWORD rc;
1529
1530 if (strstr(lpNamedPipeName,"\\\\."))
1531 {
1532 // If pipe is created on the local machine
1533 // we must delete string \\. because
1534 // in Windows named pipes scheme is a \\.\PIPE\pipename
1535 // but in OS/2 only \PIPE\pipename
1536 lpOS2Name = (LPSTR)lpNamedPipeName + 3;
1537 }
1538 else lpOS2Name = (LPSTR)lpNamedPipeName;
1539
1540 rc=DosCallNPipe(lpOS2Name,
1541 lpInBuffer,
1542 nInBufferSize,
1543 lpOutBuffer,
1544 nOutBufferSize,
1545 lpBytesRead,
1546 nTimeOut );
1547
1548
1549 if (!rc) return (TRUE);
1550 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1551
1552 return (FALSE);
1553}
1554
1555//******************************************************************************
1556//******************************************************************************
1557BOOL OSLibDosTransactNamedPipe( DWORD hNamedPipe,
1558 LPVOID lpInBuffer,
1559 DWORD nInBufferSize,
1560 LPVOID lpOutBuffer,
1561 DWORD nOutBufferSize,
1562 LPDWORD lpBytesRead,
1563 LPOVERLAPPED lpOverlapped)
1564{
1565 DWORD rc;
1566
1567 rc=DosTransactNPipe(hNamedPipe,
1568 lpOutBuffer,
1569 nOutBufferSize,
1570 lpInBuffer,
1571 nInBufferSize,
1572 lpBytesRead);
1573
1574 dprintf(("DosTransactNPipe returned rc=%d");)
1575 if (!rc) return (TRUE);
1576 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1577
1578 return (FALSE);
1579}
1580
1581//******************************************************************************
1582//******************************************************************************
1583BOOL OSLibDosPeekNamedPipe(DWORD hPipe,
1584 LPVOID lpvBuffer,
1585 DWORD cbBuffer,
1586 LPDWORD lpcbRead,
1587 LPDWORD lpcbAvail,
1588 LPDWORD lpcbMessage)
1589{
1590 DWORD rc;
1591 AVAILDATA availData ={0};
1592 ULONG ulDummy;
1593
1594 rc=DosPeekNPipe(hPipe,lpvBuffer,cbBuffer,lpcbRead,&availData,&ulDummy);
1595
1596 dprintf(("DosPeekNPipe returned rc=%d",rc));
1597
1598 if (!rc)
1599 {
1600 *lpcbAvail = availData.cbpipe;
1601 *lpcbMessage = availData.cbmessage;
1602 return (TRUE);
1603 }
1604 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1605
1606 return (FALSE);
1607}
1608//******************************************************************************
1609//******************************************************************************
1610BOOL OSLibDosDisconnectNamedPipe(DWORD hPipe)
1611{
1612 DWORD rc;
1613
1614 rc=DosDisConnectNPipe(hPipe);
1615
1616 dprintf(("DosDisConnectNPipe returned rc=%d",rc));
1617
1618 if (!rc) return TRUE;
1619 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1620
1621 return (FALSE);
1622}
1623//******************************************************************************
1624//******************************************************************************
1625BOOL OSLibDosWaitNamedPipe(LPCSTR lpszNamedPipeName,
1626 DWORD dwTimeout)
1627{
1628 LPSTR lpOS2Name;
1629 DWORD rc;
1630
1631 if (strstr(lpszNamedPipeName,"\\\\."))
1632 {
1633 // If pipe is created on the local machine
1634 // we must delete string \\. because
1635 // in Windows named pipes scheme is a \\.\PIPE\pipename
1636 // but in OS/2 only \PIPE\pipename
1637 lpOS2Name = (LPSTR)lpszNamedPipeName + 3;
1638 }
1639 else lpOS2Name = (LPSTR)lpszNamedPipeName;
1640
1641 rc=DosWaitNPipe(lpOS2Name,dwTimeout);
1642
1643 dprintf(("DosWaitNPipe returned rc=%d",rc));
1644
1645 if (!rc) return TRUE;
1646 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1647
1648 return (FALSE);
1649}
1650//******************************************************************************
1651//******************************************************************************
1652BOOL isRoot(CHAR* name)
1653{
1654 if (name[1] == ':')
1655 {
1656 //local name (x:\)
1657 return (name[2] == 0) || !strchr(&name[3],'\\');
1658 } else if (name[0] == '\\')
1659 {
1660 //UNC name (\\resource\drive\)
1661 CHAR *drive,*dir;
1662
1663 drive = strchr(&name[2],'\\');
1664 if (!drive) return FALSE;
1665 dir = strchr(&drive[1],'\\');
1666 if (!dir) return TRUE;
1667 return !strchr(&dir[1],'\\');
1668 } else return FALSE; //unknown
1669}
1670//******************************************************************************
1671//******************************************************************************
1672inline CHAR system2DOSCharacter(CHAR ch)
1673{
1674 switch(ch)
1675 {
1676 case ' ':
1677 case '.':
1678 case '~':
1679 return '_';
1680
1681 default:
1682 return toupper(ch);
1683 }
1684}
1685
1686VOID long2ShortName(CHAR* longName, CHAR* shortName)
1687{
1688 // check for uplink / root: "." and ".."
1689 if (longName[0] == '.')
1690 {
1691 // if ((strcmp(longName,".") == 0) || (strcmp(longName,"..") == 0))
1692 if (longName[1] == 0) // "."
1693 {
1694 shortName[0] = '.';
1695 shortName[1] = 0;
1696 return;
1697 }
1698
1699 if (longName[1] == '.' && longName[2] == 0) // ".."
1700 {
1701 shortName[0] = '.';
1702 shortName[1] = '.';
1703 shortName[2] = 0;
1704 return;
1705 }
1706 }
1707 else
1708 // check for empty name
1709 if(longName[0] == 0)
1710 {
1711 shortName[0] = 0;
1712 return;
1713 }
1714
1715 INT x;
1716 CHAR *source = longName;
1717
1718 // Test if longName is 8:3 compliant and simply copy
1719 // the filename.
1720 BOOL flag83 = TRUE;
1721
1722 // verify forbidden characters
1723 for (x = 0;
1724 (x < 8) &&
1725 (flag83 == TRUE);
1726 x++)
1727 {
1728 switch (*source++)
1729 {
1730 case '.': // a period will cause the loop to abort!
1731 x=1000;
1732 break;
1733
1734 case '/': case '?':
1735 case '*': case ':':
1736 case '\\': case '"':
1737 case ' ':
1738 flag83 = FALSE;
1739 break;
1740 }
1741 }
1742
1743 // verify we're on a period now
1744 if (flag83 == TRUE)
1745 if (*source != '.')
1746 flag83 = FALSE;
1747
1748 // verify extension
1749 if (flag83 == TRUE)
1750 for (INT y = 0;
1751 (y < 3) && (flag83 == TRUE);
1752 y++)
1753 {
1754 switch (*source)
1755 {
1756 case '/': case '?':
1757 case '*': case ':':
1758 case '\\': case '"':
1759 case ' ': case '.':
1760 flag83 = FALSE;
1761 break;
1762 }
1763 }
1764
1765 // verify we're at the end of the string now
1766 if (flag83 == TRUE)
1767 if (*source != 0)
1768 flag83 = FALSE;
1769
1770 // OK, done
1771 if (flag83 == TRUE)
1772 {
1773 // we might not alter any character here, since
1774 // an app opening a specific file with an 8:3 "alias",
1775 // would surely fail.
1776 strcpy(longName,
1777 shortName);
1778
1779 return; // Done
1780 }
1781
1782
1783 // @@@PH
1784 shortName[0] = 0; // this function is disabled anyway ...
1785 return;
1786
1787 CHAR *dest = shortName;
1788 CHAR *ext = strrchr(longName,'.');
1789
1790 //CB: quick and dirty, real FILE~12.EXT is too slow
1791 //PH: We'd have to count the number of non-8:3-compliant files
1792 // within a directory. Or simpler: the number of files within
1793 // the current directory.
1794
1795 //8 character file name
1796 for (x = 0;x < 8;x++)
1797 {
1798 if ((source == ext) || (source[0] == 0)) break;
1799 dest[0] = system2DOSCharacter(source[0]);
1800 source++;
1801 dest++;
1802 }
1803
1804 if (source[0] == 0)
1805 {
1806 dest[0] = 0;
1807 return;
1808 }
1809
1810 if (source != ext)
1811 {
1812 //longName > 8 characters, insert ~1
1813 shortName[6] = '~';
1814 shortName[7] = '1';
1815 }
1816
1817 if (ext)
1818 {
1819 //add extension, 3 characters
1820 dest[0] = ext[0];
1821 dest++;
1822 ext++;
1823 for (x = 0;x < 3;x++)
1824 {
1825 if (ext[0] == 0) break;
1826 dest[0] = system2DOSCharacter(ext[0]);
1827 ext++;
1828 dest++;
1829 }
1830 }
1831 dest[0] = 0;
1832}
1833//******************************************************************************
1834//******************************************************************************
1835VOID translateFileResults(FILESTATUS3 *pResult,LPWIN32_FIND_DATAA pFind,CHAR* achName)
1836{
1837 CHAR* name;
1838
1839 pFind->dwFileAttributes = pm2WinFileAttributes(pResult->attrFile);
1840
1841 pmDateTimeToFileTime(&pResult->fdateCreation,&pResult->ftimeCreation,&pFind->ftCreationTime);
1842 pmDateTimeToFileTime(&pResult->fdateLastAccess,&pResult->ftimeLastAccess,&pFind->ftLastAccessTime);
1843 pmDateTimeToFileTime(&pResult->fdateLastWrite,&pResult->ftimeLastWrite,&pFind->ftLastWriteTime);
1844
1845 pFind->nFileSizeHigh = 0; //CB: fixme
1846 pFind->nFileSizeLow = pResult->cbFile;
1847 name = strrchr(achName,'\\');
1848 if (name)
1849 {
1850 name++;
1851 strcpy(pFind->cFileName,name);
1852 }
1853 else
1854 pFind->cFileName[0] = 0;
1855
1856 long2ShortName(pFind->cFileName,pFind->cAlternateFileName);
1857}
1858
1859VOID translateFindResults(FILEFINDBUF3 *pResult,LPWIN32_FIND_DATAA pFind)
1860{
1861 pFind->dwFileAttributes = pm2WinFileAttributes(pResult->attrFile);
1862
1863 pmDateTimeToFileTime(&pResult->fdateCreation,&pResult->ftimeCreation,&pFind->ftCreationTime);
1864 pmDateTimeToFileTime(&pResult->fdateLastAccess,&pResult->ftimeLastAccess,&pFind->ftLastAccessTime);
1865 pmDateTimeToFileTime(&pResult->fdateLastWrite,&pResult->ftimeLastWrite,&pFind->ftLastWriteTime);
1866
1867 pFind->nFileSizeHigh = 0; //CB: fixme
1868 pFind->nFileSizeLow = pResult->cbFile;
1869 strcpy(pFind->cFileName,pResult->achName);
1870 long2ShortName(pFind->cFileName,pFind->cAlternateFileName);
1871}
1872//******************************************************************************
1873//******************************************************************************
1874DWORD OSLibDosFindFirst(LPCSTR lpFileName,WIN32_FIND_DATAA* lpFindFileData)
1875{
1876 HDIR hDir = -1;
1877 ULONG attrs;
1878 FILEFINDBUF3 result;
1879 ULONG searchCount = 1;
1880
1881 attrs = FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY | FILE_ARCHIVED;
1882 result.achName[0] = 0;
1883
1884 DosError(FERR_DISABLEHARDERR | FERR_DISABLEEXCEPTION);
1885 APIRET rc = DosFindFirst((PSZ)lpFileName,&hDir,attrs,&result,sizeof(result),&searchCount,FIL_STANDARD);
1886 //PH: DosError(FERR_ENABLEHARDERR | FERR_ENABLEEXCEPTION);
1887
1888 //check root: skip "." and ".." (HPFS, not on FAT)
1889 //check in OSLibDosFindNext not necessary: "." and ".." are the first two entries
1890 if ((rc == 0) && isRoot((LPSTR)lpFileName))
1891 {
1892 while ((strcmp(result.achName,".") == 0) ||
1893 (strcmp(result.achName,"..") == 0))
1894 {
1895 result.achName[0] = 0;
1896 //PH: DosError(FERR_DISABLEHARDERR | FERR_DISABLEEXCEPTION);
1897 searchCount = 1;
1898 APIRET rc = DosFindNext(hDir,&result,sizeof(result),&searchCount);
1899 //PH: DosError(FERR_ENABLEHARDERR | FERR_ENABLEEXCEPTION);
1900 if (rc)
1901 {
1902 DosFindClose(hDir);
1903 SetLastError(error2WinError(rc));
1904
1905 DosError(FERR_ENABLEHARDERR | FERR_ENABLEEXCEPTION);
1906 return INVALID_HANDLE_VALUE_W;
1907 }
1908 }
1909 }
1910
1911 // enable i/o kernel exceptions again
1912 DosError(FERR_ENABLEHARDERR | FERR_ENABLEEXCEPTION);
1913
1914 if(rc)
1915 {
1916 DosFindClose(hDir);
1917 SetLastError(error2WinError(rc));
1918 return INVALID_HANDLE_VALUE_W;
1919 }
1920 translateFindResults(&result,lpFindFileData);
1921 SetLastError(ERROR_SUCCESS_W);
1922 return hDir;
1923}
1924//******************************************************************************
1925// NOTE: returns "." and ".." in root
1926//******************************************************************************
1927DWORD OSLibDosFindFirstMulti(LPCSTR lpFileName,WIN32_FIND_DATAA *lpFindFileData,DWORD *count)
1928{
1929 HDIR hDir = -1;
1930 ULONG attrs;
1931 FILEFINDBUF3 *result,*data;
1932 ULONG searchCount = *count;
1933
1934 attrs = FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY | FILE_ARCHIVED;
1935 result = (FILEFINDBUF3*)malloc(searchCount*sizeof(FILEFINDBUF3));
1936
1937 DosError(FERR_DISABLEHARDERR | FERR_DISABLEEXCEPTION);
1938 APIRET rc = DosFindFirst((PSZ)lpFileName,&hDir,attrs,result,searchCount*sizeof(FILEFINDBUF3),&searchCount,FIL_STANDARD);
1939 DosError(FERR_ENABLEHARDERR | FERR_ENABLEEXCEPTION);
1940 if (rc)
1941 {
1942 free(result);
1943 *count = 0;
1944 SetLastError(error2WinError(rc));
1945
1946 return INVALID_HANDLE_VALUE_W;
1947 }
1948
1949 data = result;
1950 for (int x = 0;x < searchCount;x++)
1951 {
1952 translateFindResults(data,&lpFindFileData[x]);
1953 data = (FILEFINDBUF3*)(((DWORD)data)+data->oNextEntryOffset);
1954 }
1955 free(result);
1956 *count = searchCount;
1957
1958 SetLastError(ERROR_SUCCESS_W);
1959 return hDir;
1960}
1961//******************************************************************************
1962//******************************************************************************
1963BOOL OSLibDosFindNext(DWORD hFindFile,WIN32_FIND_DATAA *lpFindFileData)
1964{
1965 FILEFINDBUF3 result;
1966 ULONG searchCount = 1;
1967
1968 APIRET rc = DosFindNext((HDIR)hFindFile,&result,sizeof(result),&searchCount);
1969 if (rc)
1970 {
1971 SetLastError(error2WinError(rc));
1972
1973 return FALSE;
1974 }
1975
1976 translateFindResults(&result,lpFindFileData);
1977 SetLastError(ERROR_SUCCESS_W);
1978 return TRUE;
1979}
1980//******************************************************************************
1981//******************************************************************************
1982BOOL OSLibDosFindNextMulti(DWORD hFindFile,WIN32_FIND_DATAA *lpFindFileData,DWORD *count)
1983{
1984 FILEFINDBUF3 *result,*data;
1985 ULONG searchCount = *count;
1986
1987 result = (FILEFINDBUF3*)malloc(searchCount*sizeof(FILEFINDBUF3));
1988 APIRET rc = DosFindNext((HDIR)hFindFile,result,searchCount*sizeof(FILEFINDBUF3),&searchCount);
1989 if (rc)
1990 {
1991 free(result);
1992 *count = 0;
1993 SetLastError(error2WinError(rc));
1994
1995 return FALSE;
1996 }
1997
1998 data = result;
1999 for (int x = 0;x < searchCount;x++)
2000 {
2001 translateFindResults(data,&lpFindFileData[x]);
2002 data = (FILEFINDBUF3*)(((DWORD)data)+data->oNextEntryOffset);
2003 }
2004 free(result);
2005 *count = searchCount;
2006
2007 SetLastError(ERROR_SUCCESS_W);
2008 return TRUE;
2009}
2010//******************************************************************************
2011//******************************************************************************
2012BOOL OSLibDosFindClose(DWORD hFindFile)
2013{
2014 APIRET rc = DosFindClose((HDIR)hFindFile);
2015 if (rc)
2016 {
2017 SetLastError(error2WinError(rc));
2018 return FALSE;
2019 }
2020
2021 SetLastError(ERROR_SUCCESS_W);
2022 return TRUE;
2023}
2024//******************************************************************************
2025#define FSATTACH_SIZE 256
2026//******************************************************************************
2027DWORD OSLibDosQueryVolumeFS(int drive, LPSTR lpFileSystemNameBuffer, DWORD nFileSystemNameSize)
2028{
2029 PFSQBUFFER2 fsinfo = (PFSQBUFFER2) alloca(FSATTACH_SIZE);
2030 ULONG cb = FSATTACH_SIZE;
2031 char drv[3] = "A:";
2032 char *fsname;
2033 APIRET rc;
2034
2035 if(lpFileSystemNameBuffer == NULL) {
2036 DebugInt3();
2037 return ERROR_INVALID_PARAMETER_W;
2038 }
2039 drv[0] = (char)('A' + drive - 1);
2040
2041 DosError(FERR_DISABLEHARDERR);
2042 rc = DosQueryFSAttach(drv, 1, FSAIL_QUERYNAME, fsinfo, &cb);
2043 DosError(FERR_ENABLEHARDERR);
2044
2045 switch(rc) {
2046 case ERROR_INVALID_DRIVE:
2047 return ERROR_INVALID_DRIVE_W;
2048 case ERROR_NO_VOLUME_LABEL:
2049 return ERROR_NO_VOLUME_LABEL_W;
2050 case NO_ERROR:
2051 break;
2052 default:
2053 return ERROR_NOT_ENOUGH_MEMORY; //whatever
2054 }
2055
2056 fsname = (char *)&fsinfo->szName[0] + fsinfo->cbName + 1;
2057
2058 /* @@@PH 2000/08/10 CMD.EXE querys with nFileSystemNameSize == 0
2059 * however does NOT expect to receive an error.
2060 */
2061 strncpy(lpFileSystemNameBuffer,
2062 fsname,
2063 nFileSystemNameSize);
2064 /*
2065 if(strlen(fsname) < nFileSystemNameSize) {
2066 strcpy(lpFileSystemNameBuffer, fsname);
2067 }
2068 else return ERROR_BUFFER_OVERFLOW_W;
2069 */
2070 return 0;
2071}
2072//******************************************************************************
2073typedef struct _FSINFOBUF
2074{
2075 ULONG ulVolser; /* Volume serial number */
2076 VOLUMELABEL vol; /* Volume lable */
2077} FSINFOBUF;
2078//******************************************************************************
2079DWORD OSLibDosQueryVolumeSerialAndName(int drive, LPDWORD lpVolumeSerialNumber,
2080 LPSTR lpVolumeNameBuffer, DWORD nVolumeNameSize)
2081{
2082 FSINFOBUF fsi;
2083 APIRET rc;
2084
2085 DosError(FERR_DISABLEHARDERR);
2086 rc = DosQueryFSInfo(drive, FSIL_VOLSER, &fsi, sizeof(fsi));
2087 DosError(FERR_ENABLEHARDERR);
2088
2089 switch(rc) {
2090 case ERROR_INVALID_DRIVE:
2091 return ERROR_INVALID_DRIVE_W;
2092 case ERROR_NO_VOLUME_LABEL:
2093 return ERROR_NO_VOLUME_LABEL_W;
2094 case NO_ERROR:
2095 break;
2096 default:
2097 return ERROR_NOT_ENOUGH_MEMORY; //whatever
2098 }
2099
2100 if(lpVolumeSerialNumber) {
2101 *lpVolumeSerialNumber = fsi.ulVolser;
2102 }
2103 if(lpVolumeNameBuffer)
2104 {
2105 if(nVolumeNameSize > fsi.vol.cch) {
2106 strcpy(lpVolumeNameBuffer, (PCHAR)fsi.vol.szVolLabel);
2107 }
2108 else return ERROR_BUFFER_OVERFLOW_W;
2109 }
2110
2111 return ERROR_SUCCESS_W;
2112}
2113//******************************************************************************
2114//******************************************************************************
2115BOOL OSLibGetDiskFreeSpace(LPSTR lpRootPathName, LPDWORD lpSectorsPerCluster,
2116 LPDWORD lpBytesPerSector, LPDWORD lpNumberOfFreeClusters,
2117 LPDWORD lpTotalNumberOfClusters)
2118{
2119 ULONG diskNum;
2120 FSALLOCATE fsAlloc;
2121 APIRET rc;
2122
2123 if(lpRootPathName == 0)
2124 diskNum = 0;
2125 else
2126 if('A' <= *lpRootPathName && *lpRootPathName <= 'Z' )
2127 diskNum = *lpRootPathName - 'A' + 1;
2128 else
2129 if('a' <= *lpRootPathName && *lpRootPathName <= 'z' )
2130 diskNum = *lpRootPathName - 'a' + 1;
2131 else
2132 diskNum = 0;
2133
2134 DosError(FERR_DISABLEHARDERR);
2135 rc = DosQueryFSInfo(diskNum, FSIL_ALLOC, &fsAlloc, sizeof(fsAlloc));
2136 DosError(FERR_ENABLEHARDERR);
2137
2138 if(rc == 0)
2139 {
2140 *lpSectorsPerCluster = fsAlloc.cSectorUnit;
2141 *lpBytesPerSector = fsAlloc.cbSector;
2142 *lpNumberOfFreeClusters = fsAlloc.cUnitAvail;
2143 *lpTotalNumberOfClusters = fsAlloc.cUnit;
2144 SetLastError(ERROR_SUCCESS_W);
2145 return TRUE;
2146 }
2147 SetLastError(error2WinError(rc));
2148 return FALSE;
2149}
2150//******************************************************************************
2151//Returns bit map where with the mapping of the logical drives
2152//******************************************************************************
2153ULONG OSLibGetLogicalDrives()
2154{
2155 ULONG ulDriveNum = 0; /* Drive number (A=1, B=2, C=3, ...) */
2156 ULONG ulDriveMap = 0; /* Mapping of valid drives */
2157 APIRET rc;
2158
2159 rc = DosQueryCurrentDisk(&ulDriveNum, &ulDriveMap);
2160 if(rc) {
2161 DebugInt3();
2162 SetLastError(error2WinError(rc));
2163 return 0;
2164 }
2165 return ulDriveMap;
2166}
2167//******************************************************************************
2168//******************************************************************************
2169ULONG OSLibDosQueryCurrentDisk()
2170
2171{
2172 ULONG ulDriveNum = 0; /* Drive number (A=1, B=2, C=3, ...) */
2173 ULONG ulDriveMap = 0; /* Mapping of valid drives */
2174 APIRET rc;
2175
2176 rc = DosQueryCurrentDisk(&ulDriveNum, &ulDriveMap);
2177 if(rc) {
2178 DebugInt3();
2179 SetLastError(error2WinError(rc));
2180 return 0;
2181 }
2182 return ulDriveNum;
2183}
2184//******************************************************************************
2185//******************************************************************************
2186BOOL OSLibDosCreatePipe(PHANDLE phfRead,
2187 PHANDLE phfWrite,
2188 LPSECURITY_ATTRIBUTES lpsa,
2189 DWORD dwSize)
2190{
2191 APIRET rc;
2192
2193 dprintf(("DosCreatePipe(%08xh,%08xh,%08xh)\n",
2194 phfRead,
2195 phfWrite,
2196 dwSize));
2197
2198 // select default buffer size
2199 if (dwSize == 0)
2200 dwSize = 4096;
2201
2202 rc = DosCreatePipe(phfRead,
2203 phfWrite,
2204 dwSize);
2205 dprintf(("DosCreatePipe rc=%d",rc));
2206 if (rc)
2207 {
2208 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER_W));
2209 return -1; // INVALID_HANDLE_VALUE
2210 }
2211 SetLastError(ERROR_SUCCESS_W);
2212 return NO_ERROR;
2213}
2214//******************************************************************************
2215//******************************************************************************
2216DWORD OSLibDosDevIOCtl( DWORD hFile, DWORD dwCat, DWORD dwFunc,
2217 PVOID pParm, DWORD dwParmMaxLen, DWORD *pdwParmLen,
2218 PVOID pData, DWORD dwDataMaxLen, DWORD *pdwDataLen)
2219{
2220 APIRET rc;
2221
2222 rc = DosDevIOCtl( (HFILE)hFile, dwCat, dwFunc,
2223 pParm, dwParmMaxLen, pdwParmLen,
2224 pData, dwDataMaxLen, pdwDataLen);
2225
2226 SetLastError(error2WinError(rc,ERROR_INVALID_HANDLE));
2227 return (DWORD)rc;
2228}
2229
2230/**
2231 * Pure wrapper for DosQueryModulName which returns the OS/2 returncode.
2232 * @returns Returncode from DosQueryModuleName.
2233 * @param hModule Handle of the module which name we query.
2234 * @param cchName Length of the output name buffer.
2235 * @param pszname Pointer to the output name buffer.
2236 * @status Completely implemented.
2237 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
2238 */
2239ULONG OSLibDosQueryModuleName(ULONG hModule, int cchName, char *pszName)
2240{
2241 return DosQueryModuleName(hModule, cchName, pszName);
2242}
2243
2244
2245HINSTANCE OSLibDosLoadModule(LPSTR szModName)
2246{
2247 APIRET rc;
2248 HMODULE hModule = NULLHANDLE;
2249 char name[ CCHMAXPATH ];
2250
2251 rc = DosLoadModule(name, CCHMAXPATH, szModName, &hModule);
2252 if(rc) {
2253 SetLastError(error2WinError(rc,ERROR_FILE_NOT_FOUND));
2254 return 0;
2255 }
2256 SetLastError(ERROR_SUCCESS_W);
2257 return hModule;
2258}
2259
2260ULONG OSLibDosQuerySysInfo(ULONG iStart, ULONG iLast, PVOID pBuf, ULONG cbBuf)
2261{
2262 APIRET rc;
2263
2264 rc = DosQuerySysInfo(iStart, iLast, pBuf, cbBuf);
2265 SetLastError(error2WinError(rc,ERROR_INVALID_HANDLE));
2266 return rc;
2267}
2268//******************************************************************************
2269//returned length is number of characters required or used for current dir
2270//*excluding* terminator
2271//******************************************************************************
2272ULONG OSLibDosQueryDir(DWORD length, LPSTR lpszCurDir)
2273{
2274 ULONG drivemap, currentdisk, len;
2275 char *lpszCurDriveAndDir = lpszCurDir +3;
2276 APIRET rc;
2277
2278 len = (length > 3) ? length - 3 : 0;
2279
2280 rc = DosQueryCurrentDir(0, lpszCurDriveAndDir, &len);
2281 if(rc != ERROR_BUFFER_OVERFLOW)
2282 {
2283 if(rc)
2284 {
2285 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER));
2286 return 0;
2287 }
2288 len = strlen(lpszCurDriveAndDir) + 3;
2289
2290 // Dir returned by DosQueryCurDir doesn't include drive, so add it
2291 DosQueryCurrentDisk(&currentdisk, &drivemap);
2292
2293 if(isupper(lpszCurDir[3])) {
2294 lpszCurDir[0] = (char)('A' - 1 + currentdisk);
2295 }
2296 else lpszCurDir[0] = (char)('a' - 1 + currentdisk);
2297
2298 lpszCurDir[1] = ':';
2299 lpszCurDir[2] = '\\';
2300 }
2301 else len += 3; // + 3 since DosQueryCurDir doesn't include drive
2302
2303 SetLastError(ERROR_SUCCESS_W);
2304 return len;
2305}
2306//******************************************************************************
2307//******************************************************************************
Note: See TracBrowser for help on using the repository browser.