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

Last change on this file since 3306 was 3306, checked in by cbratschi, 25 years ago

* empty log message *

File size: 37.6 KB
Line 
1/* $Id: oslibdos.cpp,v 1.24 2000-04-02 15:11:12 cbratschi 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 *
10 * Project Odin Software License can be found in LICENSE.TXT
11 *
12 */
13#define INCL_BASE
14#define INCL_DOSEXCEPTIONS
15#define INCL_DOSMEMMGR
16#define INCL_DOSPROCESS
17#define INCL_DOSERRORS
18#define INCL_NPIPES
19#include <os2wrap.h> //Odin32 OS/2 api wrappers
20#include <stdlib.h>
21#include <stdio.h>
22#include <string.h>
23#include <ctype.h>
24#include <win32api.h>
25#include <winconst.h>
26#include <misc.h>
27#include "initterm.h"
28#include "oslibdos.h"
29#include "dosqss.h"
30
31#define DBG_LOCALLOG DBG_oslibdos
32#include "dbglocal.h"
33
34//******************************************************************************
35// translate OS/2 error codes to Windows codes
36// NOTE: add all codes you need, list is not complete!
37//******************************************************************************
38DWORD error2WinError(APIRET rc,DWORD defaultCode = ERROR_NOT_ENOUGH_MEMORY_W)
39{
40 switch (rc)
41 {
42 case NO_ERROR: //0
43 return ERROR_SUCCESS_W;
44
45 case ERROR_FILE_NOT_FOUND: //2
46 return ERROR_FILE_NOT_FOUND_W;
47
48 case ERROR_PATH_NOT_FOUND: //3
49 return ERROR_PATH_NOT_FOUND_W;
50
51 case ERROR_ACCESS_DENIED: //5
52 return ERROR_ACCESS_DENIED_W;
53
54 case ERROR_INVALID_HANDLE: //6
55 return ERROR_INVALID_HANDLE_W;
56
57 case ERROR_NOT_ENOUGH_MEMORY: //8
58 return ERROR_NOT_ENOUGH_MEMORY_W;
59
60 case ERROR_BAD_FORMAT: //11
61 return ERROR_BAD_FORMAT_W;
62
63 case ERROR_NO_MORE_FILES: //18
64 return ERROR_NO_MORE_FILES_W;
65
66 case ERROR_NOT_DOS_DISK: //26
67 return ERROR_NOT_DOS_DISK_W;
68
69 case ERROR_OUT_OF_STRUCTURES: //84
70 return ERROR_OUT_OF_STRUCTURES_W;
71
72 case ERROR_INVALID_PARAMETER: //87
73 return ERROR_INVALID_PARAMETER_W;
74
75 case ERROR_INTERRUPT: //95
76 return ERROR_INVALID_AT_INTERRUPT_TIME_W; //CB: right???
77
78 case ERROR_DRIVE_LOCKED: //108
79 return ERROR_DRIVE_LOCKED_W;
80
81 case ERROR_BROKEN_PIPE: //109
82 return ERROR_BROKEN_PIPE_W;
83
84 case ERROR_BUFFER_OVERFLOW: //111
85 return ERROR_BUFFER_OVERFLOW_W;
86
87 case ERROR_NO_MORE_SEARCH_HANDLES: //113
88 return ERROR_NO_MORE_SEARCH_HANDLES_W;
89
90 case ERROR_SEM_TIMEOUT: //121
91 return ERROR_SEM_TIMEOUT_W;
92
93 case ERROR_DISCARDED: //157
94 return ERROR_DISCARDED_W;
95
96 case ERROR_FILENAME_EXCED_RANGE: //206
97 return ERROR_FILENAME_EXCED_RANGE_W;
98
99 case ERROR_META_EXPANSION_TOO_LONG: //208
100 return ERROR_META_EXPANSION_TOO_LONG_W;
101
102 case ERROR_BAD_PIPE: //230
103 return ERROR_BAD_PIPE_W;
104
105 case ERROR_PIPE_BUSY: //231
106 return ERROR_PIPE_BUSY_W;
107
108 case ERROR_PIPE_NOT_CONNECTED: //233
109 return ERROR_PIPE_NOT_CONNECTED_W;
110
111 case ERROR_MORE_DATA: //234
112 return ERROR_MORE_DATA_W;
113
114 case ERROR_INVALID_EA_NAME: //254
115 return ERROR_INVALID_EA_NAME_W;
116
117 case ERROR_EA_LIST_INCONSISTENT: //255
118 return ERROR_EA_LIST_INCONSISTENT_W;
119
120 case ERROR_EAS_DIDNT_FIT: //275
121 return ERROR_EAS_DIDNT_FIT;
122
123 default:
124 return defaultCode;
125 }
126}
127//******************************************************************************
128//TODO: Assumes entire memory range has the same protection flags!
129//TODO: Check if this works for code aliases...
130//******************************************************************************
131DWORD OSLibDosAliasMem(LPVOID pb, ULONG cb, LPVOID *ppbAlias, ULONG fl)
132{
133 DWORD rc;
134 DWORD attr;
135 DWORD size = cb;
136
137 cb = (cb-1) & ~0xfff;
138 cb+= PAGE_SIZE;
139
140 rc = DosQueryMem(pb, &size, &attr);
141 if(rc) {
142 dprintf(("OSLibDosAliasMem: DosQueryMem %x %x return %d", pb, size, rc));
143 return rc;
144 }
145 size = (size-1) & ~0xfff;
146 size+= PAGE_SIZE;
147 if(size != cb) {
148 dprintf(("ERROR: OSLibDosAliasMem: size != cb (%x!=%x)!!!!!!!!", size, cb));
149 //ignore this and continue return 5;
150 attr = fl; //just use original protection flags (NOT CORRECT)
151 }
152 attr &= (PAG_READ|PAG_WRITE|PAG_EXECUTE|PAG_GUARD|PAG_DEFAULT);
153 if(attr != fl) {
154 rc = DosSetMem(pb, size, fl);
155 if(rc) {
156 dprintf(("OSLibDosAliasMem: DosSetMem %x %x return %d", pb, size, rc));
157 attr = fl;
158 //just continue for now
159 //return rc;
160 }
161 }
162 rc = DosAliasMem(pb, cb, ppbAlias, 2);
163 if(rc) {
164 dprintf(("OSLibDosAliasMem: DosAliasMem %x %x returned %d", pb, cb, rc));
165 return rc;
166 }
167 if(attr != fl) {
168 rc = DosSetMem(pb, size, attr);
169 if(rc) {
170 dprintf(("OSLibDosAliasMem: DosSetMem (2) %x %x return %d", pb, size, rc));
171 return rc;
172 }
173 }
174 return 0;
175}
176//******************************************************************************
177//NT returns addresses aligned at 64k, so we do too.
178//******************************************************************************
179DWORD OSLibDosAllocMem(LPVOID *lplpMemAddr, DWORD size, DWORD flags)
180{
181 LPVOID memaddr;
182 DWORD offset;
183 APIRET rc;
184
185 rc = DosAllocMem(&memaddr, size, PAG_READ | flAllocMem);
186 if(rc) {
187 return rc;
188 }
189 DosEnterCritSec();
190 DosFreeMem(memaddr);
191 offset = (DWORD)memaddr & 0xFFFF;
192 if(offset) {
193 DosAllocMem(&memaddr, 64*1024 - offset, PAG_READ | flAllocMem);
194 }
195 rc = DosAllocMem(lplpMemAddr, size, flags | flAllocMem);
196 DosExitCritSec();
197 if((DWORD)*lplpMemAddr & 0xFFFF) {//still not at 64k boundary?
198 DosFreeMem(*lplpMemAddr);
199 rc = OSLibDosAllocMem(lplpMemAddr, size, flags);
200 }
201 if(offset) {
202 DosFreeMem(memaddr);
203 }
204
205 return rc;
206}
207//******************************************************************************
208//******************************************************************************
209DWORD OSLibDosFreeMem(LPVOID lpMemAddr)
210{
211 return DosFreeMem(lpMemAddr);
212}
213//******************************************************************************
214//NOTE: If name == NULL, allocated gettable unnamed shared memory
215//******************************************************************************
216DWORD OSLibDosAllocSharedMem(LPVOID *lplpMemAddr, DWORD size, DWORD flags, LPSTR name)
217{
218 APIRET rc;
219 char *sharedmemname = NULL;
220
221 if(name) {
222 sharedmemname = (char *)malloc(strlen(name) + 16);
223 strcpy(sharedmemname, "\\SHAREMEM\\");
224 strcat(sharedmemname, name);
225 }
226 else flags |= OBJ_GETTABLE;
227
228 rc = DosAllocSharedMem(lplpMemAddr, sharedmemname, size, flags);
229 if(name) {
230 free(sharedmemname);
231 }
232 return rc;
233}
234//******************************************************************************
235//NOTE: If name == NULL, assume gettable unnamed shared memory
236//******************************************************************************
237DWORD OSLibDosGetNamedSharedMem(LPVOID *lplpMemAddr, LPSTR name)
238{
239 APIRET rc;
240 char *sharedmemname = NULL;
241
242 if(name) {
243 sharedmemname = (char *)malloc(strlen(name) + 16);
244 strcpy(sharedmemname, "\\SHAREMEM\\");
245 strcat(sharedmemname, name);
246 rc = DosGetNamedSharedMem(lplpMemAddr, sharedmemname, PAG_READ|PAG_WRITE);
247 if(name) {
248 free(sharedmemname);
249 }
250 }
251 else rc = DosGetSharedMem((LPVOID)*(DWORD *)lplpMemAddr, PAG_READ|PAG_WRITE);
252
253 return rc;
254}
255//******************************************************************************
256//******************************************************************************
257DWORD OSLibDosQueryMem(LPVOID lpMemAddr, DWORD *lpRangeSize, DWORD *lpAttr)
258{
259 return DosQueryMem(lpMemAddr, lpRangeSize, lpAttr);
260}
261//******************************************************************************
262//******************************************************************************
263DWORD OSLibDosSetMem(LPVOID lpMemAddr, DWORD size, DWORD flags)
264{
265 APIRET rc;
266
267 rc = DosSetMem(lpMemAddr, size, flags);
268 switch(rc) {
269 case ERROR_INVALID_ADDRESS:
270 return OSLIB_ERROR_INVALID_ADDRESS;
271 case ERROR_ACCESS_DENIED:
272 return OSLIB_ERROR_ACCESS_DENIED;
273 default:
274 return rc;
275 }
276}
277//******************************************************************************
278//******************************************************************************
279DWORD OSLibDosOpen(char *lpszFileName, DWORD flags)
280{
281 APIRET rc;
282 HFILE hFile;
283 ULONG ulAction;
284 DWORD os2flags = OPEN_FLAGS_NOINHERIT;
285
286
287 if(flags & OSLIB_ACCESS_READONLY)
288 os2flags |= OPEN_ACCESS_READONLY;
289 else
290 if(flags & OSLIB_ACCESS_READWRITE)
291 os2flags |= OPEN_ACCESS_READWRITE;
292
293 if(flags & OSLIB_ACCESS_SHAREDENYNONE)
294 os2flags |= OPEN_SHARE_DENYNONE;
295 else
296 if(flags & OSLIB_ACCESS_SHAREDENYREAD)
297 os2flags |= OPEN_SHARE_DENYREAD;
298 else
299 if(flags & OSLIB_ACCESS_SHAREDENYWRITE)
300 os2flags |= OPEN_SHARE_DENYWRITE;
301
302tryopen:
303 rc = DosOpen(lpszFileName, /* File path name */
304 &hFile, /* File handle */
305 &ulAction, /* Action taken */
306 0L, /* File primary allocation */
307 0L, /* File attribute */
308 OPEN_ACTION_FAIL_IF_NEW |
309 OPEN_ACTION_OPEN_IF_EXISTS, /* Open function type */
310 os2flags,
311 0L); /* No extended attribute */
312
313 if(rc) {
314 if(rc == ERROR_TOO_MANY_OPEN_FILES) {
315 ULONG CurMaxFH;
316 LONG ReqCount = 32;
317
318 rc = DosSetRelMaxFH(&ReqCount, &CurMaxFH);
319 if(rc) {
320 dprintf(("DosSetRelMaxFH returned %d", rc));
321 return 0;
322 }
323 dprintf(("DosOpen failed -> increased nr open files to %d", CurMaxFH));
324 goto tryopen;
325 }
326 return 0;
327 }
328 else return hFile;
329}
330//******************************************************************************
331//******************************************************************************
332DWORD OSLibDosClose(DWORD hFile)
333{
334 return DosClose(hFile);
335}
336//******************************************************************************
337//******************************************************************************
338DWORD OSLibDosChangeMaxFileHandles()
339{
340 ULONG CurMaxFH;
341 LONG ReqCount = 0;
342 APIRET rc;
343
344 rc = DosSetRelMaxFH(&ReqCount, &CurMaxFH);
345 if(rc) {
346 dprintf(("DosSetRelMaxFH returned %d", rc));
347 return rc;
348 }
349 if(ReqCount + ODIN_INCREMENT_MAX_FILEHANDLES > CurMaxFH) {
350 ReqCount = CurMaxFH + ODIN_INCREMENT_MAX_FILEHANDLES;
351 rc = DosSetRelMaxFH(&ReqCount, &CurMaxFH);
352 if(rc) {
353 dprintf(("DosSetRelMaxFH returned %d", rc));
354 return rc;
355 }
356 }
357 return 0;
358}
359//******************************************************************************
360//******************************************************************************
361DWORD OSLibDosSetInitialMaxFileHandles(DWORD maxhandles)
362{
363 ULONG CurMaxFH;
364 LONG ReqCount = 0;
365 APIRET rc;
366
367 rc = DosSetRelMaxFH(&ReqCount, &CurMaxFH);
368 if(rc) {
369 dprintf(("DosSetRelMaxFH returned %d", rc));
370 return rc;
371 }
372 if(CurMaxFH < maxhandles) {
373 rc = DosSetMaxFH(maxhandles);
374 if(rc) {
375 dprintf(("DosSetMaxFH returned %d", rc));
376 return rc;
377 }
378 }
379 return 0;
380}
381//******************************************************************************
382//******************************************************************************
383DWORD OSLibDosRead(DWORD hFile, LPVOID lpBuffer, DWORD size, DWORD *nrBytesRead)
384{
385 return DosRead(hFile, lpBuffer, size, nrBytesRead);
386}
387//******************************************************************************
388//******************************************************************************
389DWORD OSLibDosWrite(DWORD hFile, LPVOID lpBuffer, DWORD size, DWORD *nrBytesWritten)
390{
391 return DosWrite(hFile, lpBuffer, size, nrBytesWritten);
392}
393//******************************************************************************
394//******************************************************************************
395DWORD OSLibDosSetFilePtr(DWORD hFile, DWORD offset, DWORD method)
396{
397 DWORD os2method;
398 DWORD newoffset;
399 APIRET rc;
400
401 switch(method) {
402 case OSLIB_SETPTR_FILE_CURRENT:
403 os2method = FILE_CURRENT;
404 break;
405 case OSLIB_SETPTR_FILE_BEGIN:
406 os2method = FILE_BEGIN ;
407 break;
408 case OSLIB_SETPTR_FILE_END:
409 os2method = FILE_END;
410 break;
411 default:
412 return OSLIB_ERROR_INVALID_PARAMETER;
413 }
414 rc = DosSetFilePtr(hFile, offset, os2method, &newoffset);
415 if(rc) {
416 return -1;
417 }
418 else return newoffset;
419}
420//******************************************************************************
421//******************************************************************************
422BOOL pmDateTimeToFileTime(FDATE *pDate,FTIME *pTime,FILETIME *pFT)
423{
424 USHORT dosTime, dosDate;
425
426 dosTime = *(USHORT*)pTime;
427 dosDate = *(USHORT*)pDate;
428
429 return DosDateTimeToFileTime(dosDate,dosTime,pFT);
430}
431//******************************************************************************
432//******************************************************************************
433#define NOT_NORMAL (FILE_ATTRIBUTE_READONLY_W | \
434 FILE_ATTRIBUTE_HIDDEN_W | \
435 FILE_ATTRIBUTE_SYSTEM_W | \
436 FILE_ATTRIBUTE_ARCHIVE_W)
437
438inline DWORD pm2WinFileAttributes(DWORD attrFile)
439{
440 DWORD res = 0;
441
442 if (!(attrFile & NOT_NORMAL))
443 res |= FILE_ATTRIBUTE_NORMAL_W;
444 if (attrFile & FILE_READONLY)
445 res |= FILE_ATTRIBUTE_READONLY_W;
446 if (attrFile & FILE_HIDDEN)
447 res |= FILE_ATTRIBUTE_HIDDEN_W;
448 if (attrFile & FILE_SYSTEM)
449 res |= FILE_ATTRIBUTE_SYSTEM_W;
450 if (attrFile & FILE_DIRECTORY)
451 res |= FILE_ATTRIBUTE_DIRECTORY_W;
452 if (attrFile & FILE_ARCHIVED)
453 res |= FILE_ATTRIBUTE_ARCHIVE_W;
454
455 //CB: not used: FILE_ATTRIBUTE_COMPRESSED_W
456
457 return res;
458}
459//******************************************************************************
460//******************************************************************************
461BOOL OSLibDosGetFileAttributesEx(PSZ pszName,
462 ULONG ulDummy,
463 PVOID pBuffer)
464{
465 APIRET rc; /* API return code */
466 FILESTATUS3 fs3; /* file information structure */
467 LPWIN32_FILE_ATTRIBUTE_DATA lpFad = (LPWIN32_FILE_ATTRIBUTE_DATA) pBuffer;
468
469 // Note: we only handle standard "GetFileExInfoStandard" requests
470 rc = DosQueryPathInfo(pszName, /* query the file information */
471 FIL_STANDARD,
472 &fs3,
473 sizeof(fs3));
474 if (rc != NO_ERROR) /* check for errors */
475 return FALSE; /* raise error condition */
476
477 // convert structure
478 lpFad->dwFileAttributes = pm2WinFileAttributes(fs3.attrFile);
479 pmDateTimeToFileTime(&fs3.fdateCreation, &fs3.ftimeCreation, &lpFad->ftCreationTime);
480 pmDateTimeToFileTime(&fs3.fdateLastAccess, &fs3.ftimeLastAccess, &lpFad->ftLastAccessTime);
481 pmDateTimeToFileTime(&fs3.fdateLastWrite, &fs3.ftimeLastWrite, &lpFad->ftLastWriteTime);
482
483 /* @@@PH we might add Aurora support ...
484 lpFad->nFileSizeHigh = info.nFileSizeHigh;
485 */
486 lpFad->nFileSizeHigh = 0;
487 lpFad->nFileSizeLow = fs3.cbFile;
488
489 return TRUE;
490}
491//******************************************************************************
492DWORD WIN32API GetEnvironmentVariableA(LPCSTR, LPSTR, DWORD );
493//******************************************************************************
494DWORD OSLibDosSearchPath(DWORD cmd, char *path, char *name, char *full_name,
495 DWORD length_fullname)
496{
497 switch(cmd) {
498 case OSLIB_SEARCHDIR:
499 if(DosSearchPath(SEARCH_IGNORENETERRS, path,
500 name, full_name, length_fullname) != 0) {
501 return 0;
502 }
503 return strlen(full_name);
504
505
506 case OSLIB_SEARCHCURDIR:
507 if(DosSearchPath(SEARCH_IGNORENETERRS | SEARCH_CUR_DIRECTORY, path,
508 name, full_name, length_fullname) != 0) {
509 return 0;
510 }
511 return strlen(full_name);
512
513 case OSLIB_SEARCHFILE:
514 {
515 FILESTATUS3 fileinfo;
516
517 if(DosQueryPathInfo(name, FIL_STANDARD, &fileinfo, sizeof(fileinfo)) != 0) {
518 return 0;
519 }
520 strncpy(full_name, name, length_fullname);
521 return strlen(full_name);
522 }
523
524 case OSLIB_SEARCHENV:
525 {
526 LPSTR envstring;
527 int envsize;
528 CHAR szResult[CCHMAXPATH];
529
530 envsize = GetEnvironmentVariableA(path, NULL, 0);
531 envstring = (LPSTR)malloc(envsize+1);
532 GetEnvironmentVariableA(path, envstring, envsize);
533 if(DosSearchPath(SEARCH_IGNORENETERRS, envstring,
534 name, szResult, sizeof(szResult)) != 0) {
535 free(envstring);
536 return 0;
537 }
538 free(envstring);
539 strcpy(full_name, szResult);
540 return strlen(full_name);
541 }
542 }
543 return 0;
544}
545//******************************************************************************
546//******************************************************************************
547DWORD OSLibDosCreate(CHAR *lpFileName,
548 DWORD dwAccess,
549 DWORD dwShare,
550 LPSECURITY_ATTRIBUTES lpSecurityAttributes,
551 DWORD dwCreation,
552 DWORD dwFlags,
553 HANDLE hTemplate,
554 DWORD *dwFile)
555{
556 APIRET rc;
557 HFILE hFile;
558 ULONG ulAction=0;
559 DWORD os2Attrib=0;
560 DWORD os2Flags = 0; //OPEN_FLAGS_NOINHERIT;
561 DWORD os2Open=0;
562
563 if(dwAccess == (GENERIC_READ_W | GENERIC_WRITE_W))
564 os2Flags |= OPEN_ACCESS_READWRITE;
565 else if(dwAccess & GENERIC_WRITE_W)
566 os2Flags |= OPEN_ACCESS_WRITEONLY;
567 else if(dwAccess & GENERIC_READ_W)
568 os2Flags |= OPEN_ACCESS_READONLY;
569
570 if(dwShare == 0)
571 os2Flags |= OPEN_SHARE_DENYREADWRITE;
572 else if(dwShare == (FILE_SHARE_READ_W | FILE_SHARE_WRITE_W))
573 os2Flags |= OPEN_SHARE_DENYNONE;
574 else if(dwShare & FILE_SHARE_READ_W)
575 os2Flags |= OPEN_SHARE_DENYWRITE;
576 else if(dwShare & FILE_SHARE_WRITE_W)
577 os2Flags |= OPEN_SHARE_DENYREAD;
578
579 if(dwCreation == CREATE_NEW_W)
580 os2Open = OPEN_ACTION_FAIL_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW;
581 else if(dwCreation == CREATE_ALWAYS_W)
582 os2Open = OPEN_ACTION_REPLACE_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW;
583 else if(dwCreation == OPEN_EXISTING_W)
584 os2Open = OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW;
585 else if(dwCreation == OPEN_ALWAYS_W)
586 os2Open = OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW;
587 else if(dwCreation == TRUNCATE_EXISTING_W)
588 os2Open = OPEN_ACTION_REPLACE_IF_EXISTS;// |OPEN_ACTION_FAIL_IF_NEW;
589
590 if(dwFlags & FILE_ATTRIBUTE_READONLY_W)
591 os2Attrib |= FILE_READONLY;
592 if(dwFlags & FILE_ATTRIBUTE_HIDDEN_W)
593 os2Attrib |= FILE_HIDDEN;
594 if(dwFlags & FILE_ATTRIBUTE_SYSTEM_W)
595 os2Attrib |= FILE_SYSTEM;
596 if(dwFlags & FILE_ATTRIBUTE_DIRECTORY_W)
597 os2Attrib |= FILE_DIRECTORY;
598 if(dwFlags & FILE_ATTRIBUTE_ARCHIVE_W)
599 os2Attrib |= FILE_ARCHIVED;
600 if(dwFlags & FILE_ATTRIBUTE_NORMAL_W)
601 os2Attrib |= FILE_NORMAL;
602
603 if(dwFlags & FILE_FLAG_WRITE_THROUGH_W)
604 os2Flags |= OPEN_FLAGS_WRITE_THROUGH;
605 if(dwFlags & FILE_FLAG_NO_BUFFERING_W)
606 os2Flags |= OPEN_FLAGS_NO_CACHE;
607 if(dwFlags & FILE_FLAG_RANDOM_ACCESS_W)
608 os2Flags |= OPEN_FLAGS_RANDOM;
609 if(dwFlags & FILE_FLAG_SEQUENTIAL_SCAN_W)
610 os2Flags |= OPEN_FLAGS_SEQUENTIAL;
611
612 // TODO:
613 // if(dwFlags & FILE_FLAG_OVERLAPPED_W)
614 // if(dwFlags & FILE_FLAG_DELETE_ON_CLOSE_W
615
616 rc = DosOpen(lpFileName, &hFile, &ulAction, 0,
617 os2Attrib, os2Open, os2Flags, 0);
618
619 if(rc)
620 {
621 // TODO: TEST TEST
622 dprintf(("DosOpen Error rc:%d, try without GENERIC_WRITE_W", rc));
623 if(dwAccess & GENERIC_WRITE_W)
624 os2Flags &= ~(OPEN_ACCESS_READWRITE | OPEN_ACCESS_WRITEONLY);
625 rc = DosOpen(lpFileName, &hFile, &ulAction, 0,
626 os2Attrib, os2Open, os2Flags, 0);
627 if(rc)
628 {
629 dprintf(("DosOpen Error rc:%d os2Attrib:%X os2Open:%X os2Flags:%X",
630 rc, os2Attrib, os2Open, os2Flags));
631 hFile = -1;
632 }
633 }
634
635 *dwFile = hFile;
636 return rc;
637}
638//******************************************************************************
639//(without changing file pointer)
640//******************************************************************************
641DWORD OSLibDosGetFileSize(DWORD hFile)
642{
643 FILESTATUS3 fsts3ConfigInfo = {{0}};
644 ULONG ulBufSize = sizeof(FILESTATUS3);
645
646 DosQueryFileInfo(hFile, FIL_STANDARD, &fsts3ConfigInfo, ulBufSize);
647 return fsts3ConfigInfo.cbFile;
648}
649//******************************************************************************
650//******************************************************************************
651DWORD OSLibDosSetFilePtr2(DWORD hFile, DWORD offset, DWORD method)
652{
653 DWORD newoffset;
654 APIRET rc;
655
656
657 rc = DosSetFilePtr(hFile, offset, method, &newoffset);
658 if(rc) {
659 dprintf(("DosSetFilePtr Error rc:%d", rc));
660 return -1;
661 }
662 else return newoffset;
663}
664//******************************************************************************
665//(FlushBuffer)
666//******************************************************************************
667DWORD OSLibDosResetBuffer(DWORD hFile)
668{
669 return DosResetBuffer(hFile);
670}
671//******************************************************************************
672//******************************************************************************
673DWORD OSLibDosDupHandle(DWORD hFile, DWORD *hNew)
674{
675 *hNew = -1;
676 return DosDupHandle(hFile, hNew);
677}
678//******************************************************************************
679//******************************************************************************
680void OSLibDosDisableHardError(BOOL fTurnOff)
681{
682 DosError((fTurnOff) ? FERR_DISABLEHARDERR : FERR_ENABLEHARDERR);
683}
684//******************************************************************************
685//Returns time spent in kernel & user mode in milliseconds
686//******************************************************************************
687BOOL OSLibDosQueryProcTimes(DWORD procid, ULONG *kerneltime, ULONG *usertime)
688{
689 APIRET rc;
690 char *buf;
691 ULONG size;
692 ULONG nrthreads = 4;
693
694tryagain:
695 size = sizeof(QTOPLEVEL)+sizeof(QGLOBAL)+sizeof(QPROCESS) + nrthreads*sizeof(QTHREAD);
696 buf = (char *)malloc(size);
697 rc = DosQuerySysState(0x1, RESERVED, procid, RESERVED, (PCHAR)buf, size);
698
699 if(rc) {
700 free(buf);
701 if(rc == ERROR_BUFFER_OVERFLOW) {
702 nrthreads += 4;
703 goto tryagain;
704 }
705 return FALSE;
706 }
707 PQTOPLEVEL top = (PQTOPLEVEL)buf;
708
709 *kerneltime = 0;
710 *usertime = 0;
711 for(int i=0;i<top->procdata->threadcnt;i++) {
712 *kerneltime += top->procdata->threads[i].systime;
713 *usertime += top->procdata->threads[i].usertime;
714 }
715 free(buf);
716 return TRUE;
717}
718//******************************************************************************
719//******************************************************************************
720// TODO: implement SecurityAttributes parameter
721DWORD OSLibDosCreateNamedPipe(LPCTSTR lpName,
722 DWORD dwOpenMode,
723 DWORD dwPipeMode,
724 DWORD nMaxInstances,
725 DWORD nOutBufferSize,
726 DWORD nInBufferSize,
727 DWORD nDefaultTimeOut,
728 void* lpSecurityAttributes)
729{ DWORD dwOS2Mode = 0;
730 DWORD dwOS2PipeMode = 0;
731 LPSTR lpOS2Name;
732 DWORD hPipe;
733 DWORD rc;
734
735 if (dwOpenMode & PIPE_ACCESS_DUPLEX_W)
736 dwOS2Mode |= NP_ACCESS_DUPLEX;
737 else
738 if (dwOpenMode & PIPE_ACCESS_INBOUND_W)
739 dwOS2Mode |= NP_ACCESS_INBOUND;
740 else
741 if (dwOpenMode & PIPE_ACCESS_OUTBOUND_W)
742 dwOS2Mode |= NP_ACCESS_OUTBOUND;
743 // TODO:
744 // if(dwOpenMode & FILE_FLAG_OVERLAPPED)
745 // if(dwOpenMode & WRITE_DAC)
746 // if(dwOpenMode & WRITE_OWNER)
747 // if(dwOpenMode & ACCESS_SYSTEM_SECURITY)
748 if(dwOpenMode & FILE_FLAG_WRITE_THROUGH_W)
749 dwOS2Mode |= NP_WRITEBEHIND; // FIXME: I'm not sure!
750
751 if (dwPipeMode & PIPE_WAIT_W)
752 dwOS2PipeMode |= NP_WAIT;
753 if (dwPipeMode & PIPE_NOWAIT_W)
754 dwOS2PipeMode |= NP_NOWAIT;
755 if (dwPipeMode & PIPE_READMODE_BYTE_W)
756 dwOS2PipeMode |= NP_READMODE_BYTE;
757 if (dwPipeMode & PIPE_READMODE_MESSAGE_W)
758 dwOS2PipeMode |= NP_READMODE_MESSAGE;
759 if (dwPipeMode & PIPE_TYPE_BYTE_W)
760 dwOS2PipeMode |= NP_TYPE_BYTE;
761 if (dwPipeMode & PIPE_TYPE_MESSAGE_W)
762 dwOS2PipeMode |= NP_TYPE_MESSAGE;
763
764 if (nMaxInstances>0xff)
765 {
766 SetLastError(ERROR_INVALID_PARAMETER_W); // ERROR_INVALID_PARAMETER
767 return -1; // INVALID_HANDLE_VALUE
768 }
769 dwOS2PipeMode |= nMaxInstances;
770
771 if (strstr(lpName,"\\\\."))
772 {
773 // If pipe is created on the local machine
774 // we must delete string \\. because
775 // in Windows named pipes scheme is a \\.\PIPE\pipename
776 // but in OS/2 only \PIPE\pipename
777 lpOS2Name = (LPSTR)lpName + 3;
778 }
779 else lpOS2Name = (LPSTR)lpName;
780
781 dprintf(("DosCreateNPipe(%s,%x,%x,%x,%x,%x)",lpOS2Name,dwOS2Mode,dwOS2PipeMode,nInBufferSize,nOutBufferSize,nDefaultTimeOut));
782 rc=DosCreateNPipe(lpOS2Name,
783 &hPipe,
784 dwOS2Mode,
785 dwOS2PipeMode,
786 nInBufferSize,
787 nInBufferSize,
788 nDefaultTimeOut); // Timeouts must be tested!
789
790 dprintf(("DosCreateNPipe rc=%d",rc));
791 if (rc)
792 {
793 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER_W));
794 return -1; // INVALID_HANDLE_VALUE
795 }
796 return hPipe;
797}
798
799//******************************************************************************
800//******************************************************************************
801// TODO: implement lpOverlapped parameter!
802BOOL OSLibDosConnectNamedPipe(DWORD hNamedPipe, LPOVERLAPPED lpOverlapped)
803{
804 DWORD rc;
805
806 rc=DosConnectNPipe(hNamedPipe);
807 dprintf(("DosConnectNPipe rc=%d",rc));
808
809 if (!rc) return (TRUE);
810 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
811
812 return (FALSE);
813}
814
815//******************************************************************************
816//******************************************************************************
817BOOL OSLibDosCallNamedPipe( LPCTSTR lpNamedPipeName,
818 LPVOID lpInBuffer,
819 DWORD nInBufferSize,
820 LPVOID lpOutBuffer,
821 DWORD nOutBufferSize,
822 LPDWORD lpBytesRead,
823 DWORD nTimeOut )
824{
825 LPSTR lpOS2Name;
826 DWORD rc;
827
828 if (strstr(lpNamedPipeName,"\\\\."))
829 {
830 // If pipe is created on the local machine
831 // we must delete string \\. because
832 // in Windows named pipes scheme is a \\.\PIPE\pipename
833 // but in OS/2 only \PIPE\pipename
834 lpOS2Name = (LPSTR)lpNamedPipeName + 3;
835 }
836 else lpOS2Name = (LPSTR)lpNamedPipeName;
837
838 rc=DosCallNPipe(lpOS2Name,
839 lpInBuffer,
840 nInBufferSize,
841 lpOutBuffer,
842 nOutBufferSize,
843 lpBytesRead,
844 nTimeOut );
845
846
847 if (!rc) return (TRUE);
848 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
849
850 return (FALSE);
851}
852
853//******************************************************************************
854//******************************************************************************
855BOOL OSLibDosTransactNamedPipe( DWORD hNamedPipe,
856 LPVOID lpInBuffer,
857 DWORD nInBufferSize,
858 LPVOID lpOutBuffer,
859 DWORD nOutBufferSize,
860 LPDWORD lpBytesRead,
861 LPOVERLAPPED lpOverlapped)
862{
863 DWORD rc;
864
865 rc=DosTransactNPipe(hNamedPipe,
866 lpOutBuffer,
867 nOutBufferSize,
868 lpInBuffer,
869 nInBufferSize,
870 lpBytesRead);
871
872 dprintf(("DosTransactNPipe returned rc=%d");)
873 if (!rc) return (TRUE);
874 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
875
876 return (FALSE);
877}
878
879//******************************************************************************
880//******************************************************************************
881BOOL OSLibDosPeekNamedPipe(DWORD hPipe,
882 LPVOID lpvBuffer,
883 DWORD cbBuffer,
884 LPDWORD lpcbRead,
885 LPDWORD lpcbAvail,
886 LPDWORD lpcbMessage)
887{
888 DWORD rc;
889 AVAILDATA availData ={0};
890 ULONG ulDummy;
891
892 rc=DosPeekNPipe(hPipe,lpvBuffer,cbBuffer,lpcbRead,&availData,&ulDummy);
893
894 dprintf(("DosPeekNPipe returned rc=%d",rc));
895
896 if (!rc)
897 {
898 *lpcbAvail = availData.cbpipe;
899 *lpcbMessage = availData.cbmessage;
900 return (TRUE);
901 }
902 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
903
904 return (FALSE);
905}
906//******************************************************************************
907//******************************************************************************
908BOOL OSLibDosDisconnectNamedPipe(DWORD hPipe)
909{
910 DWORD rc;
911
912 rc=DosDisConnectNPipe(hPipe);
913
914 dprintf(("DosDisConnectNPipe returned rc=%d",rc));
915
916 if (!rc) return TRUE;
917 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
918
919 return (FALSE);
920}
921//******************************************************************************
922//******************************************************************************
923BOOL OSLibDosWaitNamedPipe(LPCSTR lpszNamedPipeName,
924 DWORD dwTimeout)
925{
926 LPSTR lpOS2Name;
927 DWORD rc;
928
929 if (strstr(lpszNamedPipeName,"\\\\."))
930 {
931 // If pipe is created on the local machine
932 // we must delete string \\. because
933 // in Windows named pipes scheme is a \\.\PIPE\pipename
934 // but in OS/2 only \PIPE\pipename
935 lpOS2Name = (LPSTR)lpszNamedPipeName + 3;
936 }
937 else lpOS2Name = (LPSTR)lpszNamedPipeName;
938
939 rc=DosWaitNPipe(lpOS2Name,dwTimeout);
940
941 dprintf(("DosWaitNPipe returned rc=%d",rc));
942
943 if (!rc) return TRUE;
944 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
945
946 return (FALSE);
947}
948//******************************************************************************
949//******************************************************************************
950BOOL isRoot(CHAR* name)
951{
952 if (name[1] == ':')
953 {
954 //local name (x:\)
955 return (name[2] == 0) || !strchr(&name[3],'\\');
956 } else if (name[0] == '\\')
957 {
958 //UNC name (\\resource\drive\)
959 CHAR *drive,*dir;
960
961 drive = strchr(&name[2],'\\');
962 if (!drive) return FALSE;
963 dir = strchr(&drive[1],'\\');
964 if (!dir) return TRUE;
965 return !strchr(&dir[1],'\\');
966 } else return FALSE; //unknown
967}
968//******************************************************************************
969//******************************************************************************
970inline CHAR system2DOSCharacter(CHAR ch)
971{
972 switch(ch)
973 {
974 case ' ':
975 case '.':
976 case '~':
977 return '_';
978
979 default:
980 return toupper(ch);
981 }
982}
983
984VOID long2ShortName(CHAR* longName,CHAR* shortName)
985{
986 INT x;
987 CHAR *source = longName,*dest = shortName,*ext = strrchr(longName,'.');
988
989 if ((strcmp(longName,".") == 0) || (strcmp(longName,"..") == 0))
990 {
991 strcpy(shortName,longName);
992 return;
993 }
994
995 //CB: quick and dirty, real FILE~12.EXT is too slow
996
997 //8 character file name
998 for (x = 0;x < 8;x++)
999 {
1000 if ((source == ext) || (source[0] == 0)) break;
1001 dest[0] = system2DOSCharacter(source[0]);
1002 source++;
1003 dest++;
1004 }
1005
1006 if (source[0] == 0)
1007 {
1008 dest[0] = 0;
1009 return;
1010 }
1011
1012 if (source != ext)
1013 {
1014 //longName > 8 characters, insert ~1
1015 shortName[6] = '~';
1016 shortName[7] = '1';
1017 }
1018
1019 if (ext)
1020 {
1021 //add extension, 3 characters
1022 dest[0] = ext[0];
1023 dest++;
1024 ext++;
1025 for (x = 0;x < 3;x++)
1026 {
1027 if (ext[0] == 0) break;
1028 dest[0] = system2DOSCharacter(ext[0]);
1029 ext++;
1030 dest++;
1031 }
1032 }
1033 dest[0] = 0;
1034}
1035//******************************************************************************
1036//******************************************************************************
1037VOID translateFileResults(FILESTATUS3 *pResult,LPWIN32_FIND_DATAA pFind,CHAR* achName)
1038{
1039 CHAR* name;
1040
1041 pFind->dwFileAttributes = pm2WinFileAttributes(pResult->attrFile);
1042
1043 pmDateTimeToFileTime(&pResult->fdateCreation,&pResult->ftimeCreation,&pFind->ftCreationTime);
1044 pmDateTimeToFileTime(&pResult->fdateLastAccess,&pResult->ftimeLastAccess,&pFind->ftLastAccessTime);
1045 pmDateTimeToFileTime(&pResult->fdateLastWrite,&pResult->ftimeLastWrite,&pFind->ftLastWriteTime);
1046
1047 pFind->nFileSizeHigh = 0; //CB: fixme
1048 pFind->nFileSizeLow = pResult->cbFile;
1049 name = strrchr(achName,'\\');
1050 if (name)
1051 {
1052 name++;
1053 strcpy(pFind->cFileName,name);
1054 } else pFind->cFileName[0] = 0;
1055 long2ShortName(pFind->cFileName,pFind->cAlternateFileName);
1056}
1057
1058VOID translateFindResults(FILEFINDBUF3 *pResult,LPWIN32_FIND_DATAA pFind)
1059{
1060 pFind->dwFileAttributes = pm2WinFileAttributes(pResult->attrFile);
1061
1062 pmDateTimeToFileTime(&pResult->fdateCreation,&pResult->ftimeCreation,&pFind->ftCreationTime);
1063 pmDateTimeToFileTime(&pResult->fdateLastAccess,&pResult->ftimeLastAccess,&pFind->ftLastAccessTime);
1064 pmDateTimeToFileTime(&pResult->fdateLastWrite,&pResult->ftimeLastWrite,&pFind->ftLastWriteTime);
1065
1066 pFind->nFileSizeHigh = 0; //CB: fixme
1067 pFind->nFileSizeLow = pResult->cbFile;
1068 strcpy(pFind->cFileName,pResult->achName);
1069 long2ShortName(pFind->cFileName,pFind->cAlternateFileName);
1070}
1071//******************************************************************************
1072//******************************************************************************
1073DWORD OSLibDosFindFirst(LPCSTR lpFileName,WIN32_FIND_DATAA* lpFindFileData)
1074{
1075 HDIR hDir = -1;
1076 ULONG attrs;
1077 FILEFINDBUF3 result;
1078 ULONG searchCount = 1;
1079
1080 attrs = FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY | FILE_ARCHIVED;
1081
1082 DosError(FERR_DISABLEHARDERR | FERR_DISABLEEXCEPTION);
1083 APIRET rc = DosFindFirst((PSZ)lpFileName,&hDir,attrs,&result,sizeof(result),&searchCount,FIL_STANDARD);
1084 DosError(FERR_ENABLEHARDERR | FERR_ENABLEEXCEPTION);
1085
1086 //check root: skip "." and ".." (HPFS, not on FAT)
1087 //check in OSLibDosFindNext not necessary: "." and ".." are the first two entries
1088 if ((rc == 0) && isRoot((LPSTR)lpFileName))
1089 {
1090 while ((strcmp(result.achName,".") == 0) || (strcmp(result.achName,"..") == 0))
1091 {
1092 DosError(FERR_DISABLEHARDERR | FERR_DISABLEEXCEPTION);
1093 searchCount = 1;
1094 APIRET rc = DosFindNext(hDir,&result,sizeof(result),&searchCount);
1095 DosError(FERR_ENABLEHARDERR | FERR_ENABLEEXCEPTION);
1096 if (rc)
1097 {
1098 DosFindClose(hDir);
1099 SetLastError(error2WinError(rc));
1100
1101 return INVALID_HANDLE_VALUE_W;
1102 }
1103 }
1104 }
1105 translateFindResults(&result,lpFindFileData);
1106
1107 return hDir;
1108}
1109//******************************************************************************
1110// NOTE: returns "." and ".." in root
1111//******************************************************************************
1112DWORD OSLibDosFindFirstMulti(LPCSTR lpFileName,WIN32_FIND_DATAA *lpFindFileData,DWORD *count)
1113{
1114 HDIR hDir = -1;
1115 ULONG attrs;
1116 FILEFINDBUF3 *result,*data;
1117 ULONG searchCount = *count;
1118
1119 attrs = FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY | FILE_ARCHIVED;
1120 result = (FILEFINDBUF3*)malloc(searchCount*sizeof(FILEFINDBUF3));
1121
1122 DosError(FERR_DISABLEHARDERR | FERR_DISABLEEXCEPTION);
1123 APIRET rc = DosFindFirst((PSZ)lpFileName,&hDir,attrs,result,searchCount*sizeof(FILEFINDBUF3),&searchCount,FIL_STANDARD);
1124 DosError(FERR_ENABLEHARDERR | FERR_ENABLEEXCEPTION);
1125 if (rc)
1126 {
1127 free(result);
1128 *count = 0;
1129 SetLastError(error2WinError(rc));
1130
1131 return INVALID_HANDLE_VALUE_W;
1132 }
1133
1134 data = result;
1135 for (int x = 0;x < searchCount;x++)
1136 {
1137 translateFindResults(data,&lpFindFileData[x]);
1138 data = (FILEFINDBUF3*)(((DWORD)data)+data->oNextEntryOffset);
1139 }
1140 free(result);
1141 *count = searchCount;
1142
1143 return hDir;
1144}
1145//******************************************************************************
1146//******************************************************************************
1147BOOL OSLibDosFindNext(DWORD hFindFile,WIN32_FIND_DATAA *lpFindFileData)
1148{
1149 FILEFINDBUF3 result;
1150 ULONG searchCount = 1;
1151
1152 APIRET rc = DosFindNext((HDIR)hFindFile,&result,sizeof(result),&searchCount);
1153 if (rc)
1154 {
1155 SetLastError(error2WinError(rc));
1156
1157 return FALSE;
1158 }
1159
1160 translateFindResults(&result,lpFindFileData);
1161
1162 return TRUE;
1163}
1164//******************************************************************************
1165//******************************************************************************
1166BOOL OSLibDosFindNextMulti(DWORD hFindFile,WIN32_FIND_DATAA *lpFindFileData,DWORD *count)
1167{
1168 FILEFINDBUF3 *result,*data;
1169 ULONG searchCount = *count;
1170
1171 result = (FILEFINDBUF3*)malloc(searchCount*sizeof(FILEFINDBUF3));
1172 APIRET rc = DosFindNext((HDIR)hFindFile,result,searchCount*sizeof(FILEFINDBUF3),&searchCount);
1173 if (rc)
1174 {
1175 free(result);
1176 *count = 0;
1177 SetLastError(error2WinError(rc));
1178
1179 return FALSE;
1180 }
1181
1182 data = result;
1183 for (int x = 0;x < searchCount;x++)
1184 {
1185 translateFindResults(data,&lpFindFileData[x]);
1186 data = (FILEFINDBUF3*)(((DWORD)data)+data->oNextEntryOffset);
1187 }
1188 free(result);
1189 *count = searchCount;
1190
1191 return TRUE;
1192}
1193//******************************************************************************
1194//******************************************************************************
1195BOOL OSLibDosFindClose(DWORD hFindFile)
1196{
1197 APIRET rc = DosFindClose((HDIR)hFindFile);
1198 if (rc)
1199 {
1200 SetLastError(error2WinError(rc));
1201
1202 return FALSE;
1203 }
1204
1205 return TRUE;
1206}
Note: See TracBrowser for help on using the repository browser.