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

Last change on this file since 4703 was 4703, checked in by bird, 25 years ago

OSLibDosCreateFile: Fix for OPEN_ACTION_REPLACE_IF_EXISTS being

incompatible with readonly access.

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