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

Last change on this file since 4763 was 4763, checked in by sandervl, 25 years ago

Rewrote GetLogicalDrives, minor fixes for GetDriveType

File size: 68.9 KB
Line 
1/* $Id: oslibdos.cpp,v 1.53 2000-12-07 12:00:23 sandervl 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 USHORT dosTime, dosDate;
587
588 dosTime = *(USHORT*)pTime;
589 dosDate = *(USHORT*)pDate;
590
591 return DosDateTimeToFileTime(dosDate,dosTime,pFT);
592}
593//******************************************************************************
594//******************************************************************************
595#define NOT_NORMAL (FILE_ATTRIBUTE_READONLY_W | \
596 FILE_ATTRIBUTE_HIDDEN_W | \
597 FILE_ATTRIBUTE_SYSTEM_W | \
598 FILE_ATTRIBUTE_ARCHIVE_W)
599
600inline DWORD pm2WinFileAttributes(DWORD attrFile)
601{
602 DWORD res = 0;
603
604 if (!(attrFile & NOT_NORMAL))
605 res |= FILE_ATTRIBUTE_NORMAL_W;
606 if (attrFile & FILE_READONLY)
607 res |= FILE_ATTRIBUTE_READONLY_W;
608 if (attrFile & FILE_HIDDEN)
609 res |= FILE_ATTRIBUTE_HIDDEN_W;
610 if (attrFile & FILE_SYSTEM)
611 res |= FILE_ATTRIBUTE_SYSTEM_W;
612 if (attrFile & FILE_DIRECTORY)
613 res |= FILE_ATTRIBUTE_DIRECTORY_W;
614 if (attrFile & FILE_ARCHIVED)
615 res |= FILE_ATTRIBUTE_ARCHIVE_W;
616
617 //CB: not used: FILE_ATTRIBUTE_COMPRESSED_W
618
619 return res;
620}
621//******************************************************************************
622//******************************************************************************
623BOOL OSLibDosGetFileAttributesEx(PSZ pszName,
624 ULONG ulDummy,
625 PVOID pBuffer)
626{
627 APIRET rc; /* API return code */
628 FILESTATUS3 fs3; /* file information structure */
629 LPWIN32_FILE_ATTRIBUTE_DATA lpFad = (LPWIN32_FILE_ATTRIBUTE_DATA) pBuffer;
630
631 // Note: we only handle standard "GetFileExInfoStandard" requests
632 rc = DosQueryPathInfo(pszName, /* query the file information */
633 FIL_STANDARD,
634 &fs3,
635 sizeof(fs3));
636 if (rc != NO_ERROR) /* check for errors */
637 return FALSE; /* raise error condition */
638
639 // convert structure
640 lpFad->dwFileAttributes = pm2WinFileAttributes(fs3.attrFile);
641 pmDateTimeToFileTime(&fs3.fdateCreation, &fs3.ftimeCreation, &lpFad->ftCreationTime);
642 pmDateTimeToFileTime(&fs3.fdateLastAccess, &fs3.ftimeLastAccess, &lpFad->ftLastAccessTime);
643 pmDateTimeToFileTime(&fs3.fdateLastWrite, &fs3.ftimeLastWrite, &lpFad->ftLastWriteTime);
644
645 /* @@@PH we might add Aurora support ...
646 lpFad->nFileSizeHigh = info.nFileSizeHigh;
647 */
648 lpFad->nFileSizeHigh = 0;
649 lpFad->nFileSizeLow = fs3.cbFile;
650
651 return TRUE;
652}
653//******************************************************************************
654DWORD WIN32API GetEnvironmentVariableA(LPCSTR, LPSTR, DWORD );
655//******************************************************************************
656DWORD OSLibDosSearchPath(DWORD cmd, char *path, char *name, char *full_name,
657 DWORD length_fullname)
658{
659 switch(cmd) {
660 case OSLIB_SEARCHDIR:
661 if(DosSearchPath(SEARCH_IGNORENETERRS, path,
662 name, full_name, length_fullname) != 0) {
663 return 0;
664 }
665 return strlen(full_name);
666
667
668 case OSLIB_SEARCHCURDIR:
669 if(DosSearchPath(SEARCH_IGNORENETERRS | SEARCH_CUR_DIRECTORY, path,
670 name, full_name, length_fullname) != 0) {
671 return 0;
672 }
673 return strlen(full_name);
674
675 case OSLIB_SEARCHFILE:
676 {
677 FILESTATUS3 fileinfo;
678
679 if(DosQueryPathInfo(name, FIL_STANDARD, &fileinfo, sizeof(fileinfo)) != 0) {
680 return 0;
681 }
682 strncpy(full_name, name, length_fullname);
683 full_name[length_fullname-1] = 0;
684 return strlen(full_name);
685 }
686
687 case OSLIB_SEARCHENV:
688 {
689 LPSTR envstring;
690 int envsize;
691 CHAR szResult[CCHMAXPATH];
692
693 envsize = GetEnvironmentVariableA(path, NULL, 0);
694 envstring = (LPSTR)malloc(envsize+1);
695 GetEnvironmentVariableA(path, envstring, envsize);
696 if(DosSearchPath(SEARCH_IGNORENETERRS, envstring,
697 name, szResult, sizeof(szResult)) != 0) {
698 free(envstring);
699 return 0;
700 }
701 free(envstring);
702 strcpy(full_name, szResult);
703 return strlen(full_name);
704 }
705 }
706 return 0;
707}
708//******************************************************************************
709//******************************************************************************
710DWORD OSLibDosQueryPathInfo(CHAR *pszPathName,
711 ULONG ulInfoLevel,
712 PVOID pInfoBuf,
713 ULONG cbInfoBuf)
714{
715 APIRET rc = DosQueryPathInfo( pszPathName, ulInfoLevel,
716 pInfoBuf, cbInfoBuf );
717
718 if(rc == ERROR_TOO_MANY_OPEN_FILES)
719 {
720 LONG reqCount = 2;
721 ULONG maxFiles;
722
723 if(DosSetRelMaxFH(&reqCount, &maxFiles) == NO_ERROR)
724 rc = DosQueryPathInfo(pszPathName, ulInfoLevel,
725 pInfoBuf, cbInfoBuf );
726 }
727 return rc;
728}
729//******************************************************************************
730//******************************************************************************
731DWORD OSLibDosCreateFile(CHAR *lpszFile,
732 DWORD fuAccess,
733 DWORD fuShare,
734 LPSECURITY_ATTRIBUTES lpSecurityAttributes,
735 DWORD fuCreate,
736 DWORD fuAttrFlags,
737 HANDLE hTemplateFile)
738{
739 HFILE hFile;
740 ULONG actionTaken = 0;
741 ULONG fileSize = 0;
742 ULONG fileAttr = FILE_NORMAL;
743 ULONG openFlag = 0;
744 ULONG openMode = 0;
745 APIRET rc = ERROR_NOT_ENOUGH_MEMORY;;
746
747 //TODO: lpSecurityAttributes (inheritance)
748
749 if(fuAttrFlags & FILE_ATTRIBUTE_ARCHIVE_W)
750 fileAttr |= FILE_ARCHIVED;
751 if(fuAttrFlags & FILE_ATTRIBUTE_HIDDEN_W)
752 fileAttr |= FILE_HIDDEN;
753 if(fuAttrFlags & FILE_ATTRIBUTE_SYSTEM_W)
754 fileAttr |= FILE_SYSTEM;
755 if(fuAttrFlags & FILE_ATTRIBUTE_READONLY_W)
756 fileAttr |= FILE_READONLY;
757 // TODO: FILE_ATTRIBUTE_TEMPORARY_W
758
759 switch(fuCreate)
760 {
761 case CREATE_NEW_W:
762 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_FAIL_IF_EXISTS;
763 break;
764 case CREATE_ALWAYS_W:
765 /* kso 2000-11-26: Not sure if OPEN_ACTION_REPLACE_IF_EXISTS is correct here! It is correct according to
766 * MSDN, but not according to "The Win32 API SuperBible". Anyway I haven't got time to check it out in
767 * NT now.
768 * The problem is that OPEN_ACTION_REPLACE_IF_EXISTS requires write access. It failes with
769 * rc = ERROR_ACCESS_DENIED (5). Quick fix, use OPEN_IF_EXIST if readonly access.
770 */
771 if (fuAccess & GENERIC_WRITE_W)
772 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS;
773 else
774 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
775 break;
776 case OPEN_EXISTING_W:
777 openFlag |= OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
778 break;
779 case OPEN_ALWAYS_W:
780 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
781 break;
782 case TRUNCATE_EXISTING_W:
783 openFlag |= OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS;
784 break;
785 }
786
787 if(fuAttrFlags & FILE_FLAG_WRITE_THROUGH_W) openMode |= OPEN_FLAGS_WRITE_THROUGH;
788 if(fuAttrFlags & FILE_FLAG_NO_BUFFERING_W) openMode |= OPEN_FLAGS_NO_CACHE;
789 if(fuAttrFlags & FILE_FLAG_RANDOM_ACCESS_W) openMode |= OPEN_FLAGS_RANDOM;
790 if(fuAttrFlags & FILE_FLAG_SEQUENTIAL_SCAN_W) openMode |= OPEN_FLAGS_SEQUENTIAL;
791 // TODO: FILE_FLAG_BACKUP_SEMANTICS_W
792 // FILE_FLAG_POSIX_SEMANTICS_W are not supported
793
794 //TODO: FILE_SHARE_DELETE
795 if((fuShare & (FILE_SHARE_READ_W | FILE_SHARE_WRITE_W)) == 0 )
796 openMode |= OPEN_SHARE_DENYREADWRITE;
797 else
798 if((fuShare & (FILE_SHARE_READ_W | FILE_SHARE_WRITE_W)) == (FILE_SHARE_READ_W | FILE_SHARE_WRITE_W))
799 openMode |= OPEN_SHARE_DENYNONE;
800 else
801 if(fuShare & FILE_SHARE_READ_W)
802 openMode |= OPEN_SHARE_DENYWRITE;
803 else
804 if(fuShare & FILE_SHARE_WRITE_W)
805 openMode |= OPEN_SHARE_DENYREAD;
806
807 if(fuAccess == (GENERIC_READ_W | GENERIC_WRITE_W))
808 openMode |= OPEN_ACCESS_READWRITE;
809 else
810 if(fuAccess & GENERIC_READ_W)
811 openMode |= OPEN_ACCESS_READONLY;
812 else
813 if(fuAccess & GENERIC_WRITE_W)
814 openMode |= OPEN_ACCESS_WRITEONLY;
815
816#if 0
817 //SvL: Not true; verified in NT! (also messed up access of files on
818 // readonly volumes)
819 // CreateFile with OPEN_ALWAYS & GENERIC_READ on non-existing file
820 // -> creates 0 size file, WriteFile is not allowed
821 // Same in OS/2.
822 /* if creating a file, access cannot be readonly! */
823 if (openFlag & OPEN_ACTION_CREATE_IF_NEW &&
824 (!(openMode & OPEN_ACCESS_READWRITE) &&
825 !(openMode & OPEN_ACCESS_WRITEONLY))) {
826 openMode |= OPEN_ACCESS_READWRITE;
827 }
828#endif
829
830 if(strlen(lpszFile) == 2 && lpszFile[1] == ':') {
831 //app tries to open physical disk
832 openMode |= OPEN_FLAGS_DASD;
833 }
834 int retry = 0;
835 while (retry < 3)
836 {
837 dprintf(("DosOpen %s openFlag=%x openMode=%x", lpszFile, openFlag, openMode));
838 rc = DosOpen((PSZ)lpszFile,
839 &hFile,
840 &actionTaken,
841 fileSize,
842 fileAttr,
843 openFlag,
844 openMode,
845 NULL);
846 if (rc == ERROR_TOO_MANY_OPEN_FILES)
847 {
848 ULONG CurMaxFH;
849 LONG ReqCount = 32;
850
851 rc = DosSetRelMaxFH(&ReqCount, &CurMaxFH);
852 if(rc) {
853 dprintf(("DosSetRelMaxFH returned %d", rc));
854 SetLastError(ERROR_TOO_MANY_OPEN_FILES_W);
855 return INVALID_HANDLE_VALUE_W;
856 }
857 dprintf(("DosOpen failed -> increased nr open files to %d", CurMaxFH));
858 }
859 #if 0
860 else if (rc == ERROR_ACCESS_DENIED && (openFlag & OPEN_ACTION_REPLACE_IF_EXISTS))
861 { /* kso: I have great problems with the REPLACE not working
862 * So, I guess this emulation may help...
863 * This problem exist on WS4eB SMP FP1 and Warp4 FP14/Kernel 14059 at least.
864 */
865 rc = DosOpen((PSZ)lpszFile,
866 &hFile,
867 &actionTaken,
868 fileSize,
869 fileAttr,
870 (openFlag & ~OPEN_ACTION_REPLACE_IF_EXISTS) | OPEN_ACTION_OPEN_IF_EXISTS,
871 openMode,
872 NULL);
873 if (rc == NO_ERROR)
874 {
875 rc = DosSetFileSize(hFile, 0);
876 if (!rc && fileSize > 0)
877 rc = DosSetFileSize(hFile, fileSize);
878 if (rc)
879 {
880 DosClose(hFile);
881 hFile = NULLHANDLE;
882
883 if (rc != ERROR_TOO_MANY_OPEN_FILES)
884 break;
885 }
886 else break;
887 }
888 }
889 #endif
890 else break;
891 retry++;
892 }
893
894 if(rc)
895 {
896 SetLastError(error2WinError(rc));
897 return INVALID_HANDLE_VALUE_W;
898 }
899 SetLastError(ERROR_SUCCESS_W);
900 return hFile;
901}
902//******************************************************************************
903//******************************************************************************
904DWORD OSLibDosOpenFile(CHAR *lpszFile, UINT fuMode)
905{
906 ULONG actionTaken = 0;
907 ULONG fileSize = 0;
908 ULONG fileAttr = FILE_NORMAL;
909 ULONG openFlag = 0;
910 ULONG openMode = 0;
911 APIRET rc = ERROR_NOT_ENOUGH_MEMORY;
912 HFILE hFile;
913
914 if(!(fuMode & (OF_CREATE_W | OF_READWRITE_W | OF_WRITE_W)))
915 {
916 openMode |= OPEN_ACCESS_READONLY;
917 openFlag |= OPEN_ACTION_OPEN_IF_EXISTS;
918 }
919 else
920 {
921 if(fuMode & OF_CREATE_W) {
922 openFlag |= OPEN_ACTION_CREATE_IF_NEW |
923 OPEN_ACTION_REPLACE_IF_EXISTS;
924 }
925 else openFlag |= OPEN_ACTION_OPEN_IF_EXISTS;
926
927 if(fuMode & OF_READWRITE_W)
928 openMode |= OPEN_ACCESS_READWRITE;
929 else
930 if(fuMode & OF_WRITE_W)
931 openMode |= OPEN_ACCESS_WRITEONLY;
932 else
933 if(fuMode & OF_CREATE_W)
934 openMode |= OPEN_ACCESS_READWRITE;
935 }
936
937 if((fuMode & OF_SHARE_DENY_WRITE_W) ||
938 !(fuMode & (OF_SHARE_DENY_READ_W | OF_SHARE_DENY_NONE_W | OF_SHARE_EXCLUSIVE_W)))
939 openMode |= OPEN_SHARE_DENYWRITE;
940 else
941 if (fuMode & OF_SHARE_DENY_NONE_W)
942 openMode |= OPEN_SHARE_DENYNONE;
943 else
944 if (fuMode & OF_SHARE_DENY_READ_W)
945 openMode |= OPEN_SHARE_DENYREAD;
946 else
947 if (fuMode & OF_SHARE_EXCLUSIVE_W)
948 openMode |= OPEN_SHARE_DENYREADWRITE;
949
950 rc = DosOpen((PSZ)lpszFile,
951 &hFile,
952 &actionTaken,
953 fileSize,
954 fileAttr,
955 openFlag,
956 openMode,
957 NULL);
958
959 if(rc != NO_ERROR)
960 {
961 if(fuMode & OF_EXIST_W)
962 {
963 if(rc == ERROR_OPEN_FAILED || rc == ERROR_FILE_NOT_FOUND)
964 {
965 SetLastError(ERROR_FILE_NOT_FOUND_W);
966 return HFILE_ERROR_W;
967 }
968 }
969 if((rc == ERROR_OPEN_FAILED) && (openFlag & OPEN_ACTION_OPEN_IF_EXISTS))
970 {
971 SetLastError(ERROR_FILE_NOT_FOUND_W);
972 }
973 else SetLastError(error2WinError(rc));
974
975 return HFILE_ERROR_W;
976 }
977 SetLastError(ERROR_SUCCESS_W);
978 return hFile;
979}
980//******************************************************************************
981//******************************************************************************
982BOOL OSLibDosLockFile(DWORD hFile, DWORD dwFlags,
983 DWORD OffsetLow, DWORD OffsetHigh,
984 DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh,
985 LPOVERLAPPED lpOverlapped)
986{
987 APIRET rc;
988
989 // Set 5 secs timeout for locking file and no other can access this
990 // file region
991
992 if(lpOverlapped) {//TODO:
993 dprintf(("OSLibDosLockFile: overlapped lock not yet implemented!!"));
994 }
995 //TODO: Locking region crossing end of file is permitted. Works in OS/2??
996 if(f64BitIO)
997 {
998 FILELOCKL lockRangeL;
999
1000 lockRangeL.lOffset.ulLo = OffsetLow;
1001 lockRangeL.lOffset.ulHi = OffsetHigh;
1002 lockRangeL.lRange.ulLo = nNumberOfBytesToLockLow;
1003 lockRangeL.lRange.ulHi = nNumberOfBytesToLockHigh;
1004
1005 rc = OdinDosSetFileLocksL(hFile, NULL, &lockRangeL,
1006 (dwFlags & LOCKFILE_FAIL_IMMEDIATELY_W) ? 0 : 5000, 0);
1007 //SvL: 64 bits values are only supported by JFS
1008 // Try the 32 bits DosSetFileLocks if it fails
1009 // (TODO: should check the partition type instead)
1010 if(rc == ERROR_INVALID_PARAMETER && (OffsetHigh || nNumberOfBytesToLockHigh)) {
1011 goto oldlock;
1012 }
1013 }
1014 else
1015 {
1016oldlock:
1017 FILELOCK lockRange = { OffsetLow, nNumberOfBytesToLockLow };
1018
1019 rc = DosSetFileLocks(hFile, NULL, &lockRange,
1020 (dwFlags & LOCKFILE_FAIL_IMMEDIATELY_W) ? 0 : 5000, 0);
1021 }
1022 if(rc) {
1023 SetLastError(error2WinError(rc));
1024 return FALSE;
1025 }
1026 SetLastError(ERROR_SUCCESS_W);
1027 return TRUE;
1028}
1029//******************************************************************************
1030//******************************************************************************
1031BOOL OSLibDosUnlockFile(DWORD hFile, DWORD OffsetLow, DWORD OffsetHigh,
1032 DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh,
1033 LPOVERLAPPED lpOverlapped)
1034{
1035 APIRET rc;
1036
1037 // Set 5 secs timeout for unlocking file and no other can access this
1038 // file region
1039
1040 if(lpOverlapped) {//TODO:
1041 dprintf(("OSLibDosUnlockFile: overlapped unlock not yet implemented!!"));
1042 }
1043 if(f64BitIO)
1044 {
1045 FILELOCKL unlockRangeL;
1046
1047 unlockRangeL.lOffset.ulLo = OffsetLow;
1048 unlockRangeL.lOffset.ulHi = OffsetHigh;
1049 unlockRangeL.lRange.ulLo = nNumberOfBytesToLockLow;
1050 unlockRangeL.lRange.ulHi = nNumberOfBytesToLockHigh;
1051
1052 rc = OdinDosSetFileLocksL(hFile, &unlockRangeL, NULL, 5000, 0);
1053 //SvL: 64 bits values are only supported by JFS
1054 // Try the 32 bits DosSetFileLocks if it fails
1055 // (TODO: should check the partition type instead)
1056 if(rc == ERROR_INVALID_PARAMETER && (OffsetHigh || nNumberOfBytesToLockHigh)) {
1057 goto oldlock;
1058 }
1059 }
1060 else
1061 {
1062oldlock:
1063 FILELOCK unlockRange = { OffsetLow, nNumberOfBytesToLockLow };
1064
1065 rc = DosSetFileLocks(hFile, &unlockRange, NULL, 5000, 0);
1066 }
1067 if(rc) {
1068 SetLastError(error2WinError(rc));
1069 return FALSE;
1070 }
1071 SetLastError(ERROR_SUCCESS_W);
1072 return TRUE;
1073}
1074//******************************************************************************
1075//******************************************************************************
1076BOOL OSLibDosFlushFileBuffers(DWORD hFile)
1077{
1078 APIRET rc;
1079
1080 rc = DosResetBuffer(hFile);
1081 SetLastError(error2WinError(rc));
1082 return (rc == NO_ERROR);
1083}
1084//******************************************************************************
1085//******************************************************************************
1086DWORD OSLibDosGetFileSize(DWORD hFile, LPDWORD lpdwFileSizeHigh)
1087{
1088 APIRET rc;
1089 ULONG sizeLow;
1090
1091 if(f64BitIO)
1092 {
1093 FILESTATUS3L fsts3ConfigInfoL = {{0}};
1094 ULONG ulBufSize = sizeof(FILESTATUS3L);
1095
1096 rc = DosQueryFileInfo(hFile, FIL_STANDARDL, &fsts3ConfigInfoL, ulBufSize);
1097 if(lpdwFileSizeHigh) {
1098 *lpdwFileSizeHigh = fsts3ConfigInfoL.cbFile.ulHi;
1099 }
1100 sizeLow = fsts3ConfigInfoL.cbFile.ulLo;
1101 }
1102 else
1103 {
1104 FILESTATUS3 fsts3ConfigInfo = {{0}};
1105 ULONG ulBufSize = sizeof(FILESTATUS3);
1106
1107 if(lpdwFileSizeHigh) {
1108 *lpdwFileSizeHigh = 0;
1109 }
1110 rc = DosQueryFileInfo(hFile, FIL_STANDARD, &fsts3ConfigInfo, ulBufSize);
1111 sizeLow = fsts3ConfigInfo.cbFile;
1112 }
1113 if(rc) {
1114 SetLastError(error2WinError(rc));
1115 return -1;
1116 }
1117 SetLastError(ERROR_SUCCESS_W);
1118 return sizeLow;
1119}
1120//******************************************************************************
1121//******************************************************************************
1122DWORD OSLibDosSetFilePointer(DWORD hFile, DWORD OffsetLow, DWORD *OffsetHigh, DWORD method)
1123{
1124 LONGLONG offsetL;
1125 LONGLONG newoffsetL;
1126 APIRET rc;
1127 DWORD newoffset;
1128
1129 switch(method)
1130 {
1131 case FILE_BEGIN_W:
1132 method = FILE_BEGIN;
1133 break;
1134
1135 case FILE_CURRENT_W:
1136 method = FILE_CURRENT;
1137 break;
1138
1139 case FILE_END_W:
1140 method = FILE_END;
1141 break;
1142 }
1143
1144 // PH Note: for a negative 32-bit seek, the OS/2 64-bit version
1145 // needs to be skipped.
1146 if( (f64BitIO) && (OffsetHigh) )
1147 {
1148 offsetL.ulLo = OffsetLow;
1149 offsetL.ulHi = (OffsetHigh) ? *OffsetHigh : 0;
1150 rc = OdinDosSetFilePtrL(hFile, offsetL, method, &newoffsetL);
1151 if(OffsetHigh) {
1152 *OffsetHigh = newoffsetL.ulHi;
1153 }
1154 newoffset = newoffsetL.ulLo;
1155 }
1156 else rc = DosSetFilePtr(hFile, OffsetLow, method, &newoffset);
1157
1158 if(rc)
1159 {
1160 SetLastError(error2WinError(rc));
1161 return -1;
1162 }
1163 SetLastError(ERROR_SUCCESS_W);
1164 return newoffset;
1165}
1166//******************************************************************************
1167//******************************************************************************
1168BOOL OSLibDosSetEndOfFile(DWORD hFile)
1169{
1170 ULONG newFilePos;
1171 LONGLONG FilePosL = {0,0};
1172 LONGLONG newFilePosL;
1173 APIRET rc;
1174
1175 if(f64BitIO) {
1176 rc = OdinDosSetFilePtrL(hFile, FilePosL, FILE_CURRENT, &newFilePosL);
1177 if(rc == 0) {
1178 rc = OdinDosSetFileSizeL(hFile, newFilePosL);
1179 }
1180 }
1181 else {
1182 rc = DosSetFilePtr(hFile, 0, FILE_CURRENT, &newFilePos);
1183 if(rc == 0) {
1184 rc = DosSetFileSize(hFile, newFilePos);
1185 }
1186 }
1187 if(rc) {
1188 SetLastError(error2WinError(rc));
1189 return FALSE;
1190 }
1191 SetLastError(ERROR_SUCCESS_W);
1192 return TRUE;
1193}
1194//******************************************************************************
1195//******************************************************************************
1196BOOL OSLibDosGetFileInformationByHandle(DWORD hFile, BY_HANDLE_FILE_INFORMATION* pInfo)
1197{
1198 APIRET rc;
1199
1200 if(f64BitIO)
1201 {
1202 FILESTATUS4L statusL = { 0 };
1203
1204 rc = DosQueryFileInfo(hFile, FIL_QUERYEASIZEL,
1205 &statusL, sizeof(statusL));
1206 if(rc == NO_ERROR)
1207 {
1208 pInfo->dwFileAttributes = 0;
1209 if(!(statusL.attrFile & NOT_NORMAL))
1210 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_NORMAL_W;
1211 if(statusL.attrFile & FILE_READONLY)
1212 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_READONLY_W;
1213 if(statusL.attrFile & FILE_HIDDEN)
1214 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN_W;
1215 if(statusL.attrFile & FILE_SYSTEM)
1216 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_SYSTEM_W;
1217 if(statusL.attrFile & FILE_DIRECTORY)
1218 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY_W;
1219 if(statusL.attrFile & FILE_ARCHIVED)
1220 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_ARCHIVE_W;
1221
1222 pmDateTimeToFileTime(&statusL.fdateCreation,
1223 &statusL.ftimeCreation,
1224 &pInfo->ftCreationTime);
1225 pmDateTimeToFileTime(&statusL.fdateLastAccess,
1226 &statusL.ftimeLastAccess,
1227 &pInfo->ftLastAccessTime);
1228 pmDateTimeToFileTime(&statusL.fdateLastWrite,
1229 &statusL.ftimeLastWrite,
1230 &pInfo->ftLastWriteTime);
1231
1232 pInfo->nFileSizeHigh = statusL.cbFile.ulHi;
1233 pInfo->nFileSizeLow = statusL.cbFile.ulLo;
1234 pInfo->dwVolumeSerialNumber = 0; //todo
1235 pInfo->nNumberOfLinks = 1;
1236 pInfo->nFileIndexHigh = 0;
1237 pInfo->nFileIndexLow = 0;
1238 }
1239 }
1240 else
1241 {
1242 FILESTATUS4 status = { 0 };
1243
1244 rc = DosQueryFileInfo(hFile, FIL_QUERYEASIZE, &status,
1245 sizeof(status));
1246 if(rc == NO_ERROR)
1247 {
1248 pInfo->dwFileAttributes = 0;
1249 if(!(status.attrFile & NOT_NORMAL))
1250 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_NORMAL_W;
1251 if(status.attrFile & FILE_READONLY)
1252 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_READONLY_W;
1253 if(status.attrFile & FILE_HIDDEN)
1254 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN_W;
1255 if(status.attrFile & FILE_SYSTEM)
1256 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_SYSTEM_W;
1257 if(status.attrFile & FILE_DIRECTORY)
1258 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY_W;
1259 if(status.attrFile & FILE_ARCHIVED)
1260 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_ARCHIVE_W;
1261
1262 pmDateTimeToFileTime(&status.fdateCreation,
1263 &status.ftimeCreation,
1264 &pInfo->ftCreationTime);
1265 pmDateTimeToFileTime(&status.fdateLastAccess,
1266 &status.ftimeLastAccess,
1267 &pInfo->ftLastAccessTime);
1268 pmDateTimeToFileTime(&status.fdateLastWrite,
1269 &status.ftimeLastWrite,
1270 &pInfo->ftLastWriteTime);
1271
1272 pInfo->nFileSizeHigh = 0;
1273 pInfo->nFileSizeLow = status.cbFile;
1274 pInfo->dwVolumeSerialNumber = 0; //todo
1275 pInfo->nNumberOfLinks = 1;
1276 pInfo->nFileIndexHigh = 0;
1277 pInfo->nFileIndexLow = 0;
1278 }
1279 }
1280 if(rc) {
1281 SetLastError(error2WinError(rc));
1282 return FALSE;
1283 }
1284 SetLastError(ERROR_SUCCESS_W);
1285 return TRUE;
1286}
1287//******************************************************************************
1288//******************************************************************************
1289BOOL OSLibDosSetFileTime(DWORD hFile, WORD creationdate, WORD creationtime,
1290 WORD lastaccessdate, WORD lastaccesstime,
1291 WORD lastwritedate, WORD lastwritetime)
1292{
1293 FILESTATUS3 fileInfo;
1294 APIRET rc;
1295
1296 rc = DosQueryFileInfo(hFile, FIL_STANDARD, &fileInfo, sizeof(fileInfo));
1297
1298 if(rc == NO_ERROR)
1299 {
1300 if(creationdate && creationtime) {
1301 fileInfo.fdateCreation = *(FDATE *)&creationdate;
1302 fileInfo.ftimeCreation = *(FTIME *)&creationtime;
1303 }
1304 if(lastaccessdate && lastaccesstime) {
1305 fileInfo.fdateLastAccess = *(FDATE *)&lastaccessdate;
1306 fileInfo.ftimeLastAccess = *(FTIME *)&lastaccesstime;
1307 }
1308 if(lastwritedate && lastwritetime) {
1309 fileInfo.fdateLastWrite = *(FDATE *)&lastwritedate;
1310 fileInfo.ftimeLastWrite = *(FTIME *)&lastwritetime;
1311 }
1312
1313 rc = DosSetFileInfo(hFile, FIL_STANDARD, &fileInfo, sizeof(fileInfo));
1314 }
1315
1316 if(rc)
1317 {
1318 SetLastError(error2WinError(rc));
1319 return FALSE;
1320 }
1321 SetLastError(ERROR_SUCCESS_W);
1322 return TRUE;
1323}
1324//******************************************************************************
1325//******************************************************************************
1326BOOL OSLibDosGetFileTime(DWORD hFile, WORD *creationdate, WORD *creationtime,
1327 WORD *lastaccessdate, WORD *lastaccesstime,
1328 WORD *lastwritedate, WORD *lastwritetime)
1329{
1330 FILESTATUS3 fileInfo;
1331 APIRET rc;
1332
1333 rc = DosQueryFileInfo(hFile, FIL_STANDARD, &fileInfo, sizeof(fileInfo));
1334
1335 if(rc == NO_ERROR)
1336 {
1337 *creationdate = *(WORD *)&fileInfo.fdateCreation;
1338 *creationtime = *(WORD *)&fileInfo.ftimeCreation;
1339 *lastaccessdate = *(WORD *)&fileInfo.fdateLastAccess;
1340 *lastaccesstime = *(WORD *)&fileInfo.ftimeLastAccess;
1341 *lastwritedate = *(WORD *)&fileInfo.fdateLastWrite;
1342 *lastwritetime = *(WORD *)&fileInfo.ftimeLastWrite;
1343 }
1344
1345 if(rc)
1346 {
1347 SetLastError(error2WinError(rc));
1348 return FALSE;
1349 }
1350 SetLastError(ERROR_SUCCESS_W);
1351 return TRUE;
1352}
1353//******************************************************************************
1354//******************************************************************************
1355DWORD OSLibDosSetFilePtr2(DWORD hFile, DWORD offset, DWORD method)
1356{
1357 DWORD newoffset;
1358 APIRET rc;
1359
1360
1361 rc = DosSetFilePtr(hFile, offset, method, &newoffset);
1362 if(rc) {
1363 dprintf(("DosSetFilePtr Error rc:%d", rc));
1364 return -1;
1365 }
1366 else return newoffset;
1367}
1368//******************************************************************************
1369//******************************************************************************
1370DWORD OSLibDosDupHandle(DWORD hFile, DWORD *hNew)
1371{
1372 *hNew = -1;
1373 return DosDupHandle(hFile, hNew);
1374}
1375//******************************************************************************
1376//******************************************************************************
1377void OSLibDosDisableHardError(BOOL fTurnOff)
1378{
1379 DosError((fTurnOff) ? FERR_DISABLEHARDERR : FERR_ENABLEHARDERR);
1380}
1381//******************************************************************************
1382//Returns time spent in kernel & user mode in milliseconds
1383//******************************************************************************
1384BOOL OSLibDosQueryProcTimes(DWORD procid, ULONG *kerneltime, ULONG *usertime)
1385{
1386 APIRET rc;
1387 char *buf;
1388 ULONG size;
1389 ULONG nrthreads = 4;
1390
1391tryagain:
1392 size = sizeof(QTOPLEVEL)+sizeof(QGLOBAL)+sizeof(QPROCESS) + nrthreads*sizeof(QTHREAD);
1393 buf = (char *)malloc(size);
1394 rc = DosQuerySysState(0x1, RESERVED, procid, RESERVED, (PCHAR)buf, size);
1395
1396 if(rc) {
1397 free(buf);
1398 if(rc == ERROR_BUFFER_OVERFLOW) {
1399 nrthreads += 4;
1400 goto tryagain;
1401 }
1402 return FALSE;
1403 }
1404 PQTOPLEVEL top = (PQTOPLEVEL)buf;
1405
1406 *kerneltime = 0;
1407 *usertime = 0;
1408 for(int i=0;i<top->procdata->threadcnt;i++) {
1409 *kerneltime += top->procdata->threads[i].systime;
1410 *usertime += top->procdata->threads[i].usertime;
1411 }
1412 free(buf);
1413 return TRUE;
1414}
1415//******************************************************************************
1416//******************************************************************************
1417// TODO: implement SecurityAttributes parameter
1418DWORD OSLibDosCreateNamedPipe(LPCTSTR lpName,
1419 DWORD dwOpenMode,
1420 DWORD dwPipeMode,
1421 DWORD nMaxInstances,
1422 DWORD nOutBufferSize,
1423 DWORD nInBufferSize,
1424 DWORD nDefaultTimeOut,
1425 LPSECURITY_ATTRIBUTES lpSecurityAttributes)
1426{ DWORD dwOS2Mode = 0;
1427 DWORD dwOS2PipeMode = 0;
1428 LPSTR lpOS2Name;
1429 DWORD hPipe;
1430 DWORD rc;
1431
1432 if (dwOpenMode & PIPE_ACCESS_DUPLEX_W)
1433 dwOS2Mode |= NP_ACCESS_DUPLEX;
1434 else
1435 if (dwOpenMode & PIPE_ACCESS_INBOUND_W)
1436 dwOS2Mode |= NP_ACCESS_INBOUND;
1437 else
1438 if (dwOpenMode & PIPE_ACCESS_OUTBOUND_W)
1439 dwOS2Mode |= NP_ACCESS_OUTBOUND;
1440 // TODO:
1441 // if(dwOpenMode & FILE_FLAG_OVERLAPPED)
1442 // if(dwOpenMode & WRITE_DAC)
1443 // if(dwOpenMode & WRITE_OWNER)
1444 // if(dwOpenMode & ACCESS_SYSTEM_SECURITY)
1445 if(dwOpenMode & FILE_FLAG_WRITE_THROUGH_W)
1446 dwOS2Mode |= NP_WRITEBEHIND; // FIXME: I'm not sure!
1447
1448 if (dwPipeMode & PIPE_WAIT_W)
1449 dwOS2PipeMode |= NP_WAIT;
1450 if (dwPipeMode & PIPE_NOWAIT_W)
1451 dwOS2PipeMode |= NP_NOWAIT;
1452 if (dwPipeMode & PIPE_READMODE_BYTE_W)
1453 dwOS2PipeMode |= NP_READMODE_BYTE;
1454 if (dwPipeMode & PIPE_READMODE_MESSAGE_W)
1455 dwOS2PipeMode |= NP_READMODE_MESSAGE;
1456 if (dwPipeMode & PIPE_TYPE_BYTE_W)
1457 dwOS2PipeMode |= NP_TYPE_BYTE;
1458 if (dwPipeMode & PIPE_TYPE_MESSAGE_W)
1459 dwOS2PipeMode |= NP_TYPE_MESSAGE;
1460
1461 if (nMaxInstances>0xff)
1462 {
1463 SetLastError(ERROR_INVALID_PARAMETER_W); // ERROR_INVALID_PARAMETER
1464 return -1; // INVALID_HANDLE_VALUE
1465 }
1466 dwOS2PipeMode |= nMaxInstances;
1467
1468 if (strstr(lpName,"\\\\."))
1469 {
1470 // If pipe is created on the local machine
1471 // we must delete string \\. because
1472 // in Windows named pipes scheme is a \\.\PIPE\pipename
1473 // but in OS/2 only \PIPE\pipename
1474 lpOS2Name = (LPSTR)lpName + 3;
1475 }
1476 else lpOS2Name = (LPSTR)lpName;
1477
1478 dprintf(("DosCreateNPipe(%s,%x,%x,%x,%x,%x)",lpOS2Name,dwOS2Mode,dwOS2PipeMode,nInBufferSize,nOutBufferSize,nDefaultTimeOut));
1479 rc=DosCreateNPipe(lpOS2Name,
1480 &hPipe,
1481 dwOS2Mode,
1482 dwOS2PipeMode,
1483 nInBufferSize,
1484 nInBufferSize,
1485 nDefaultTimeOut); // Timeouts must be tested!
1486
1487 dprintf(("DosCreateNPipe rc=%d",rc));
1488 if (rc)
1489 {
1490 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER_W));
1491 return -1; // INVALID_HANDLE_VALUE
1492 }
1493 return hPipe;
1494}
1495
1496//******************************************************************************
1497//******************************************************************************
1498// TODO: implement lpOverlapped parameter!
1499BOOL OSLibDosConnectNamedPipe(DWORD hNamedPipe, LPOVERLAPPED lpOverlapped)
1500{
1501 DWORD rc;
1502
1503 rc=DosConnectNPipe(hNamedPipe);
1504 dprintf(("DosConnectNPipe rc=%d",rc));
1505
1506 if (!rc) return (TRUE);
1507 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1508
1509 return (FALSE);
1510}
1511
1512//******************************************************************************
1513//******************************************************************************
1514BOOL OSLibDosCallNamedPipe( LPCTSTR lpNamedPipeName,
1515 LPVOID lpInBuffer,
1516 DWORD nInBufferSize,
1517 LPVOID lpOutBuffer,
1518 DWORD nOutBufferSize,
1519 LPDWORD lpBytesRead,
1520 DWORD nTimeOut )
1521{
1522 LPSTR lpOS2Name;
1523 DWORD rc;
1524
1525 if (strstr(lpNamedPipeName,"\\\\."))
1526 {
1527 // If pipe is created on the local machine
1528 // we must delete string \\. because
1529 // in Windows named pipes scheme is a \\.\PIPE\pipename
1530 // but in OS/2 only \PIPE\pipename
1531 lpOS2Name = (LPSTR)lpNamedPipeName + 3;
1532 }
1533 else lpOS2Name = (LPSTR)lpNamedPipeName;
1534
1535 rc=DosCallNPipe(lpOS2Name,
1536 lpInBuffer,
1537 nInBufferSize,
1538 lpOutBuffer,
1539 nOutBufferSize,
1540 lpBytesRead,
1541 nTimeOut );
1542
1543
1544 if (!rc) return (TRUE);
1545 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1546
1547 return (FALSE);
1548}
1549
1550//******************************************************************************
1551//******************************************************************************
1552BOOL OSLibDosTransactNamedPipe( DWORD hNamedPipe,
1553 LPVOID lpInBuffer,
1554 DWORD nInBufferSize,
1555 LPVOID lpOutBuffer,
1556 DWORD nOutBufferSize,
1557 LPDWORD lpBytesRead,
1558 LPOVERLAPPED lpOverlapped)
1559{
1560 DWORD rc;
1561
1562 rc=DosTransactNPipe(hNamedPipe,
1563 lpOutBuffer,
1564 nOutBufferSize,
1565 lpInBuffer,
1566 nInBufferSize,
1567 lpBytesRead);
1568
1569 dprintf(("DosTransactNPipe returned rc=%d");)
1570 if (!rc) return (TRUE);
1571 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1572
1573 return (FALSE);
1574}
1575
1576//******************************************************************************
1577//******************************************************************************
1578BOOL OSLibDosPeekNamedPipe(DWORD hPipe,
1579 LPVOID lpvBuffer,
1580 DWORD cbBuffer,
1581 LPDWORD lpcbRead,
1582 LPDWORD lpcbAvail,
1583 LPDWORD lpcbMessage)
1584{
1585 DWORD rc;
1586 AVAILDATA availData ={0};
1587 ULONG ulDummy;
1588
1589 rc=DosPeekNPipe(hPipe,lpvBuffer,cbBuffer,lpcbRead,&availData,&ulDummy);
1590
1591 dprintf(("DosPeekNPipe returned rc=%d",rc));
1592
1593 if (!rc)
1594 {
1595 *lpcbAvail = availData.cbpipe;
1596 *lpcbMessage = availData.cbmessage;
1597 return (TRUE);
1598 }
1599 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1600
1601 return (FALSE);
1602}
1603//******************************************************************************
1604//******************************************************************************
1605BOOL OSLibDosDisconnectNamedPipe(DWORD hPipe)
1606{
1607 DWORD rc;
1608
1609 rc=DosDisConnectNPipe(hPipe);
1610
1611 dprintf(("DosDisConnectNPipe returned rc=%d",rc));
1612
1613 if (!rc) return TRUE;
1614 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1615
1616 return (FALSE);
1617}
1618//******************************************************************************
1619//******************************************************************************
1620BOOL OSLibDosWaitNamedPipe(LPCSTR lpszNamedPipeName,
1621 DWORD dwTimeout)
1622{
1623 LPSTR lpOS2Name;
1624 DWORD rc;
1625
1626 if (strstr(lpszNamedPipeName,"\\\\."))
1627 {
1628 // If pipe is created on the local machine
1629 // we must delete string \\. because
1630 // in Windows named pipes scheme is a \\.\PIPE\pipename
1631 // but in OS/2 only \PIPE\pipename
1632 lpOS2Name = (LPSTR)lpszNamedPipeName + 3;
1633 }
1634 else lpOS2Name = (LPSTR)lpszNamedPipeName;
1635
1636 rc=DosWaitNPipe(lpOS2Name,dwTimeout);
1637
1638 dprintf(("DosWaitNPipe returned rc=%d",rc));
1639
1640 if (!rc) return TRUE;
1641 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1642
1643 return (FALSE);
1644}
1645//******************************************************************************
1646//******************************************************************************
1647BOOL isRoot(CHAR* name)
1648{
1649 if (name[1] == ':')
1650 {
1651 //local name (x:\)
1652 return (name[2] == 0) || !strchr(&name[3],'\\');
1653 } else if (name[0] == '\\')
1654 {
1655 //UNC name (\\resource\drive\)
1656 CHAR *drive,*dir;
1657
1658 drive = strchr(&name[2],'\\');
1659 if (!drive) return FALSE;
1660 dir = strchr(&drive[1],'\\');
1661 if (!dir) return TRUE;
1662 return !strchr(&dir[1],'\\');
1663 } else return FALSE; //unknown
1664}
1665//******************************************************************************
1666//******************************************************************************
1667inline CHAR system2DOSCharacter(CHAR ch)
1668{
1669 switch(ch)
1670 {
1671 case ' ':
1672 case '.':
1673 case '~':
1674 return '_';
1675
1676 default:
1677 return toupper(ch);
1678 }
1679}
1680
1681VOID long2ShortName(CHAR* longName,CHAR* shortName)
1682{
1683 INT x;
1684 CHAR *source = longName,*dest = shortName,*ext = strrchr(longName,'.');
1685
1686 if ((strcmp(longName,".") == 0) || (strcmp(longName,"..") == 0))
1687 {
1688 strcpy(shortName,longName);
1689 return;
1690 }
1691
1692 //CB: quick and dirty, real FILE~12.EXT is too slow
1693
1694 //8 character file name
1695 for (x = 0;x < 8;x++)
1696 {
1697 if ((source == ext) || (source[0] == 0)) break;
1698 dest[0] = system2DOSCharacter(source[0]);
1699 source++;
1700 dest++;
1701 }
1702
1703 if (source[0] == 0)
1704 {
1705 dest[0] = 0;
1706 return;
1707 }
1708
1709 if (source != ext)
1710 {
1711 //longName > 8 characters, insert ~1
1712 shortName[6] = '~';
1713 shortName[7] = '1';
1714 }
1715
1716 if (ext)
1717 {
1718 //add extension, 3 characters
1719 dest[0] = ext[0];
1720 dest++;
1721 ext++;
1722 for (x = 0;x < 3;x++)
1723 {
1724 if (ext[0] == 0) break;
1725 dest[0] = system2DOSCharacter(ext[0]);
1726 ext++;
1727 dest++;
1728 }
1729 }
1730 dest[0] = 0;
1731}
1732//******************************************************************************
1733//******************************************************************************
1734VOID translateFileResults(FILESTATUS3 *pResult,LPWIN32_FIND_DATAA pFind,CHAR* achName)
1735{
1736 CHAR* name;
1737
1738 pFind->dwFileAttributes = pm2WinFileAttributes(pResult->attrFile);
1739
1740 pmDateTimeToFileTime(&pResult->fdateCreation,&pResult->ftimeCreation,&pFind->ftCreationTime);
1741 pmDateTimeToFileTime(&pResult->fdateLastAccess,&pResult->ftimeLastAccess,&pFind->ftLastAccessTime);
1742 pmDateTimeToFileTime(&pResult->fdateLastWrite,&pResult->ftimeLastWrite,&pFind->ftLastWriteTime);
1743
1744 pFind->nFileSizeHigh = 0; //CB: fixme
1745 pFind->nFileSizeLow = pResult->cbFile;
1746 name = strrchr(achName,'\\');
1747 if (name)
1748 {
1749 name++;
1750 strcpy(pFind->cFileName,name);
1751 } else pFind->cFileName[0] = 0;
1752 long2ShortName(pFind->cFileName,pFind->cAlternateFileName);
1753}
1754
1755VOID translateFindResults(FILEFINDBUF3 *pResult,LPWIN32_FIND_DATAA pFind)
1756{
1757 pFind->dwFileAttributes = pm2WinFileAttributes(pResult->attrFile);
1758
1759 pmDateTimeToFileTime(&pResult->fdateCreation,&pResult->ftimeCreation,&pFind->ftCreationTime);
1760 pmDateTimeToFileTime(&pResult->fdateLastAccess,&pResult->ftimeLastAccess,&pFind->ftLastAccessTime);
1761 pmDateTimeToFileTime(&pResult->fdateLastWrite,&pResult->ftimeLastWrite,&pFind->ftLastWriteTime);
1762
1763 pFind->nFileSizeHigh = 0; //CB: fixme
1764 pFind->nFileSizeLow = pResult->cbFile;
1765 strcpy(pFind->cFileName,pResult->achName);
1766 long2ShortName(pFind->cFileName,pFind->cAlternateFileName);
1767}
1768//******************************************************************************
1769//******************************************************************************
1770DWORD OSLibDosFindFirst(LPCSTR lpFileName,WIN32_FIND_DATAA* lpFindFileData)
1771{
1772 HDIR hDir = -1;
1773 ULONG attrs;
1774 FILEFINDBUF3 result;
1775 ULONG searchCount = 1;
1776
1777 attrs = FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY | FILE_ARCHIVED;
1778 result.achName[0] = 0;
1779
1780 DosError(FERR_DISABLEHARDERR | FERR_DISABLEEXCEPTION);
1781 APIRET rc = DosFindFirst((PSZ)lpFileName,&hDir,attrs,&result,sizeof(result),&searchCount,FIL_STANDARD);
1782 DosError(FERR_ENABLEHARDERR | FERR_ENABLEEXCEPTION);
1783
1784 //check root: skip "." and ".." (HPFS, not on FAT)
1785 //check in OSLibDosFindNext not necessary: "." and ".." are the first two entries
1786 if ((rc == 0) && isRoot((LPSTR)lpFileName))
1787 {
1788 while ((strcmp(result.achName,".") == 0) || (strcmp(result.achName,"..") == 0))
1789 {
1790 result.achName[0] = 0;
1791 DosError(FERR_DISABLEHARDERR | FERR_DISABLEEXCEPTION);
1792 searchCount = 1;
1793 APIRET rc = DosFindNext(hDir,&result,sizeof(result),&searchCount);
1794 DosError(FERR_ENABLEHARDERR | FERR_ENABLEEXCEPTION);
1795 if (rc)
1796 {
1797 DosFindClose(hDir);
1798 SetLastError(error2WinError(rc));
1799
1800 return INVALID_HANDLE_VALUE_W;
1801 }
1802 }
1803 }
1804 if(rc) {
1805 DosFindClose(hDir);
1806 SetLastError(error2WinError(rc));
1807 return INVALID_HANDLE_VALUE_W;
1808 }
1809 translateFindResults(&result,lpFindFileData);
1810 SetLastError(ERROR_SUCCESS_W);
1811 return hDir;
1812}
1813//******************************************************************************
1814// NOTE: returns "." and ".." in root
1815//******************************************************************************
1816DWORD OSLibDosFindFirstMulti(LPCSTR lpFileName,WIN32_FIND_DATAA *lpFindFileData,DWORD *count)
1817{
1818 HDIR hDir = -1;
1819 ULONG attrs;
1820 FILEFINDBUF3 *result,*data;
1821 ULONG searchCount = *count;
1822
1823 attrs = FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY | FILE_ARCHIVED;
1824 result = (FILEFINDBUF3*)malloc(searchCount*sizeof(FILEFINDBUF3));
1825
1826 DosError(FERR_DISABLEHARDERR | FERR_DISABLEEXCEPTION);
1827 APIRET rc = DosFindFirst((PSZ)lpFileName,&hDir,attrs,result,searchCount*sizeof(FILEFINDBUF3),&searchCount,FIL_STANDARD);
1828 DosError(FERR_ENABLEHARDERR | FERR_ENABLEEXCEPTION);
1829 if (rc)
1830 {
1831 free(result);
1832 *count = 0;
1833 SetLastError(error2WinError(rc));
1834
1835 return INVALID_HANDLE_VALUE_W;
1836 }
1837
1838 data = result;
1839 for (int x = 0;x < searchCount;x++)
1840 {
1841 translateFindResults(data,&lpFindFileData[x]);
1842 data = (FILEFINDBUF3*)(((DWORD)data)+data->oNextEntryOffset);
1843 }
1844 free(result);
1845 *count = searchCount;
1846
1847 SetLastError(ERROR_SUCCESS_W);
1848 return hDir;
1849}
1850//******************************************************************************
1851//******************************************************************************
1852BOOL OSLibDosFindNext(DWORD hFindFile,WIN32_FIND_DATAA *lpFindFileData)
1853{
1854 FILEFINDBUF3 result;
1855 ULONG searchCount = 1;
1856
1857 APIRET rc = DosFindNext((HDIR)hFindFile,&result,sizeof(result),&searchCount);
1858 if (rc)
1859 {
1860 SetLastError(error2WinError(rc));
1861
1862 return FALSE;
1863 }
1864
1865 translateFindResults(&result,lpFindFileData);
1866 SetLastError(ERROR_SUCCESS_W);
1867 return TRUE;
1868}
1869//******************************************************************************
1870//******************************************************************************
1871BOOL OSLibDosFindNextMulti(DWORD hFindFile,WIN32_FIND_DATAA *lpFindFileData,DWORD *count)
1872{
1873 FILEFINDBUF3 *result,*data;
1874 ULONG searchCount = *count;
1875
1876 result = (FILEFINDBUF3*)malloc(searchCount*sizeof(FILEFINDBUF3));
1877 APIRET rc = DosFindNext((HDIR)hFindFile,result,searchCount*sizeof(FILEFINDBUF3),&searchCount);
1878 if (rc)
1879 {
1880 free(result);
1881 *count = 0;
1882 SetLastError(error2WinError(rc));
1883
1884 return FALSE;
1885 }
1886
1887 data = result;
1888 for (int x = 0;x < searchCount;x++)
1889 {
1890 translateFindResults(data,&lpFindFileData[x]);
1891 data = (FILEFINDBUF3*)(((DWORD)data)+data->oNextEntryOffset);
1892 }
1893 free(result);
1894 *count = searchCount;
1895
1896 SetLastError(ERROR_SUCCESS_W);
1897 return TRUE;
1898}
1899//******************************************************************************
1900//******************************************************************************
1901BOOL OSLibDosFindClose(DWORD hFindFile)
1902{
1903 APIRET rc = DosFindClose((HDIR)hFindFile);
1904 if (rc)
1905 {
1906 SetLastError(error2WinError(rc));
1907 return FALSE;
1908 }
1909
1910 SetLastError(ERROR_SUCCESS_W);
1911 return TRUE;
1912}
1913//******************************************************************************
1914#define FSATTACH_SIZE 256
1915//******************************************************************************
1916DWORD OSLibDosQueryVolumeFS(int drive, LPSTR lpFileSystemNameBuffer, DWORD nFileSystemNameSize)
1917{
1918 PFSQBUFFER2 fsinfo = (PFSQBUFFER2) alloca(FSATTACH_SIZE);
1919 ULONG cb = FSATTACH_SIZE;
1920 char drv[3] = "A:";
1921 char *fsname;
1922 APIRET rc;
1923
1924 if(lpFileSystemNameBuffer == NULL) {
1925 DebugInt3();
1926 return ERROR_INVALID_PARAMETER_W;
1927 }
1928 drv[0] = (char)('A' + drive - 1);
1929
1930 DosError(FERR_DISABLEHARDERR);
1931 rc = DosQueryFSAttach(drv, 1, FSAIL_QUERYNAME, fsinfo, &cb);
1932 DosError(FERR_ENABLEHARDERR);
1933
1934 switch(rc) {
1935 case ERROR_INVALID_DRIVE:
1936 return ERROR_INVALID_DRIVE_W;
1937 case ERROR_NO_VOLUME_LABEL:
1938 return ERROR_NO_VOLUME_LABEL_W;
1939 case NO_ERROR:
1940 break;
1941 default:
1942 return ERROR_NOT_ENOUGH_MEMORY; //whatever
1943 }
1944
1945 fsname = (char *)&fsinfo->szName[0] + fsinfo->cbName + 1;
1946
1947 /* @@@PH 2000/08/10 CMD.EXE querys with nFileSystemNameSize == 0
1948 * however does NOT expect to receive an error.
1949 */
1950 strncpy(lpFileSystemNameBuffer,
1951 fsname,
1952 nFileSystemNameSize);
1953 /*
1954 if(strlen(fsname) < nFileSystemNameSize) {
1955 strcpy(lpFileSystemNameBuffer, fsname);
1956 }
1957 else return ERROR_BUFFER_OVERFLOW_W;
1958 */
1959 return 0;
1960}
1961//******************************************************************************
1962typedef struct _FSINFOBUF
1963{
1964 ULONG ulVolser; /* Volume serial number */
1965 VOLUMELABEL vol; /* Volume lable */
1966} FSINFOBUF;
1967//******************************************************************************
1968DWORD OSLibDosQueryVolumeSerialAndName(int drive, LPDWORD lpVolumeSerialNumber,
1969 LPSTR lpVolumeNameBuffer, DWORD nVolumeNameSize)
1970{
1971 FSINFOBUF fsi;
1972 APIRET rc;
1973
1974 DosError(FERR_DISABLEHARDERR);
1975 rc = DosQueryFSInfo(drive, FSIL_VOLSER, &fsi, sizeof(fsi));
1976 DosError(FERR_ENABLEHARDERR);
1977
1978 switch(rc) {
1979 case ERROR_INVALID_DRIVE:
1980 return ERROR_INVALID_DRIVE_W;
1981 case ERROR_NO_VOLUME_LABEL:
1982 return ERROR_NO_VOLUME_LABEL_W;
1983 case NO_ERROR:
1984 break;
1985 default:
1986 return ERROR_NOT_ENOUGH_MEMORY; //whatever
1987 }
1988
1989 if(lpVolumeSerialNumber) {
1990 *lpVolumeSerialNumber = fsi.ulVolser;
1991 }
1992 if(lpVolumeNameBuffer)
1993 {
1994 if(nVolumeNameSize > fsi.vol.cch) {
1995 strcpy(lpVolumeNameBuffer, (PCHAR)fsi.vol.szVolLabel);
1996 }
1997 else return ERROR_BUFFER_OVERFLOW_W;
1998 }
1999
2000 return ERROR_SUCCESS_W;
2001}
2002//******************************************************************************
2003//******************************************************************************
2004BOOL OSLibGetDiskFreeSpace(LPSTR lpRootPathName, LPDWORD lpSectorsPerCluster,
2005 LPDWORD lpBytesPerSector, LPDWORD lpNumberOfFreeClusters,
2006 LPDWORD lpTotalNumberOfClusters)
2007{
2008 ULONG diskNum;
2009 FSALLOCATE fsAlloc;
2010 APIRET rc;
2011
2012 if(lpRootPathName == 0)
2013 diskNum = 0;
2014 else
2015 if('A' <= *lpRootPathName && *lpRootPathName <= 'Z' )
2016 diskNum = *lpRootPathName - 'A' + 1;
2017 else
2018 if('a' <= *lpRootPathName && *lpRootPathName <= 'z' )
2019 diskNum = *lpRootPathName - 'a' + 1;
2020 else
2021 diskNum = 0;
2022
2023 DosError(FERR_DISABLEHARDERR);
2024 rc = DosQueryFSInfo(diskNum, FSIL_ALLOC, &fsAlloc, sizeof(fsAlloc));
2025 DosError(FERR_ENABLEHARDERR);
2026
2027 if(rc == 0)
2028 {
2029 *lpSectorsPerCluster = fsAlloc.cSectorUnit;
2030 *lpBytesPerSector = fsAlloc.cbSector;
2031 *lpNumberOfFreeClusters = fsAlloc.cUnitAvail;
2032 *lpTotalNumberOfClusters = fsAlloc.cUnit;
2033 SetLastError(ERROR_SUCCESS_W);
2034 return TRUE;
2035 }
2036 SetLastError(error2WinError(rc));
2037 return FALSE;
2038}
2039//******************************************************************************
2040//Returns bit map where with the mapping of the logical drives
2041//******************************************************************************
2042ULONG OSLibGetLogicalDrives()
2043{
2044 ULONG ulDriveNum = 0; /* Drive number (A=1, B=2, C=3, ...) */
2045 ULONG ulDriveMap = 0; /* Mapping of valid drives */
2046 APIRET rc;
2047
2048 rc = DosQueryCurrentDisk(&ulDriveNum, &ulDriveMap);
2049 if(rc) {
2050 DebugInt3();
2051 SetLastError(error2WinError(rc));
2052 return 0;
2053 }
2054 return ulDriveMap;
2055}
2056//******************************************************************************
2057//******************************************************************************
2058ULONG OSLibDosQueryCurrentDisk()
2059
2060{
2061 ULONG ulDriveNum = 0; /* Drive number (A=1, B=2, C=3, ...) */
2062 ULONG ulDriveMap = 0; /* Mapping of valid drives */
2063 APIRET rc;
2064
2065 rc = DosQueryCurrentDisk(&ulDriveNum, &ulDriveMap);
2066 if(rc) {
2067 DebugInt3();
2068 SetLastError(error2WinError(rc));
2069 return 0;
2070 }
2071 return ulDriveNum;
2072}
2073//******************************************************************************
2074//******************************************************************************
2075BOOL OSLibDosCreatePipe(PHANDLE phfRead,
2076 PHANDLE phfWrite,
2077 LPSECURITY_ATTRIBUTES lpsa,
2078 DWORD dwSize)
2079{
2080 APIRET rc;
2081
2082 dprintf(("DosCreatePipe(%08xh,%08xh,%08xh)\n",
2083 phfRead,
2084 phfWrite,
2085 dwSize));
2086
2087 // select default buffer size
2088 if (dwSize == 0)
2089 dwSize = 4096;
2090
2091 rc = DosCreatePipe(phfRead,
2092 phfWrite,
2093 dwSize);
2094 dprintf(("DosCreatePipe rc=%d",rc));
2095 if (rc)
2096 {
2097 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER_W));
2098 return -1; // INVALID_HANDLE_VALUE
2099 }
2100 SetLastError(ERROR_SUCCESS_W);
2101 return NO_ERROR;
2102}
2103//******************************************************************************
2104//******************************************************************************
2105DWORD OSLibDosDevIOCtl( DWORD hFile, DWORD dwCat, DWORD dwFunc,
2106 PVOID pParm, DWORD dwParmMaxLen, DWORD *pdwParmLen,
2107 PVOID pData, DWORD dwDataMaxLen, DWORD *pdwDataLen)
2108{
2109 APIRET rc;
2110
2111 rc = DosDevIOCtl( (HFILE)hFile, dwCat, dwFunc,
2112 pParm, dwParmMaxLen, pdwParmLen,
2113 pData, dwDataMaxLen, pdwDataLen);
2114
2115 SetLastError(error2WinError(rc,ERROR_INVALID_HANDLE));
2116 return (DWORD)rc;
2117}
2118
2119/**
2120 * Pure wrapper for DosQueryModulName which returns the OS/2 returncode.
2121 * @returns Returncode from DosQueryModuleName.
2122 * @param hModule Handle of the module which name we query.
2123 * @param cchName Length of the output name buffer.
2124 * @param pszname Pointer to the output name buffer.
2125 * @status Completely implemented.
2126 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
2127 */
2128ULONG OSLibDosQueryModuleName(ULONG hModule, int cchName, char *pszName)
2129{
2130 return DosQueryModuleName(hModule, cchName, pszName);
2131}
2132
2133
2134HINSTANCE OSLibDosLoadModule(LPSTR szModName)
2135{
2136 APIRET rc;
2137 HMODULE hModule = NULLHANDLE;
2138 char name[ CCHMAXPATH ];
2139
2140 rc = DosLoadModule(name, CCHMAXPATH, szModName, &hModule);
2141 if(rc) {
2142 SetLastError(error2WinError(rc,ERROR_FILE_NOT_FOUND));
2143 return 0;
2144 }
2145 SetLastError(ERROR_SUCCESS_W);
2146 return hModule;
2147}
2148
2149ULONG OSLibDosQuerySysInfo(ULONG iStart, ULONG iLast, PVOID pBuf, ULONG cbBuf)
2150{
2151 APIRET rc;
2152
2153 rc = DosQuerySysInfo(iStart, iLast, pBuf, cbBuf);
2154 SetLastError(error2WinError(rc,ERROR_INVALID_HANDLE));
2155 return rc;
2156}
2157//******************************************************************************
2158//returned length is number of characters required or used for current dir
2159//*excluding* terminator
2160//******************************************************************************
2161ULONG OSLibDosQueryDir(DWORD length, LPSTR lpszCurDir)
2162{
2163 ULONG drivemap, currentdisk, len;
2164 char *lpszCurDriveAndDir = lpszCurDir +3;
2165 APIRET rc;
2166
2167 len = (length > 3) ? length - 3 : 0;
2168
2169 rc = DosQueryCurrentDir(0, lpszCurDriveAndDir, &len);
2170 if(rc != ERROR_BUFFER_OVERFLOW)
2171 {
2172 if(rc)
2173 {
2174 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER));
2175 return 0;
2176 }
2177 len = strlen(lpszCurDriveAndDir) + 3;
2178
2179 // Dir returned by DosQueryCurDir doesn't include drive, so add it
2180 DosQueryCurrentDisk(&currentdisk, &drivemap);
2181
2182 if(isupper(lpszCurDir[3])) {
2183 lpszCurDir[0] = (char)('A' - 1 + currentdisk);
2184 }
2185 else lpszCurDir[0] = (char)('a' - 1 + currentdisk);
2186
2187 lpszCurDir[1] = ':';
2188 lpszCurDir[2] = '\\';
2189 }
2190 else len += 3; // + 3 since DosQueryCurDir doesn't include drive
2191
2192 SetLastError(ERROR_SUCCESS_W);
2193 return len;
2194}
2195//******************************************************************************
2196//******************************************************************************
Note: See TracBrowser for help on using the repository browser.