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

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

Use DosAllocMemEx to 64KB align memory objects in the high private arena.

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