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

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

KS: OSLibDosAllocMem fix

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