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

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

vio, thread exit fixes

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