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

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

GetFileTime bugfix + FindResource(Ex)A/W changes + setup thread security objects during creation

File size: 38.0 KB
Line 
1/* $Id: oslibdos.cpp,v 1.27 2000-05-22 19:07:58 sandervl Exp $ */
2/*
3 * Wrappers for OS/2 Dos* API
4 *
5 * Copyright 1998-2000 Sander van Leeuwen (sandervl@xs4all.nl)
6 * Copyright 1999-2000 Edgar Buerkle <Edgar.Buerkle@gmx.net>
7 * Copyright 2000 Przemyslaw Dobrowolski <dobrawka@asua.org.pl>
8 * Copyright 2000 Christoph Bratschi (cbratschi@datacomm.ch)
9 *
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//******************************************************************************
422DWORD OSLibDosDelete(char *lpszFileName)
423{
424 return DosDelete(lpszFileName);
425}
426//******************************************************************************
427//******************************************************************************
428BOOL pmDateTimeToFileTime(FDATE *pDate,FTIME *pTime,FILETIME *pFT)
429{
430 USHORT dosTime, dosDate;
431
432 dosTime = *(USHORT*)pTime;
433 dosDate = *(USHORT*)pDate;
434
435 return DosDateTimeToFileTime(dosDate,dosTime,pFT);
436}
437//******************************************************************************
438//******************************************************************************
439#define NOT_NORMAL (FILE_ATTRIBUTE_READONLY_W | \
440 FILE_ATTRIBUTE_HIDDEN_W | \
441 FILE_ATTRIBUTE_SYSTEM_W | \
442 FILE_ATTRIBUTE_ARCHIVE_W)
443
444inline DWORD pm2WinFileAttributes(DWORD attrFile)
445{
446 DWORD res = 0;
447
448 if (!(attrFile & NOT_NORMAL))
449 res |= FILE_ATTRIBUTE_NORMAL_W;
450 if (attrFile & FILE_READONLY)
451 res |= FILE_ATTRIBUTE_READONLY_W;
452 if (attrFile & FILE_HIDDEN)
453 res |= FILE_ATTRIBUTE_HIDDEN_W;
454 if (attrFile & FILE_SYSTEM)
455 res |= FILE_ATTRIBUTE_SYSTEM_W;
456 if (attrFile & FILE_DIRECTORY)
457 res |= FILE_ATTRIBUTE_DIRECTORY_W;
458 if (attrFile & FILE_ARCHIVED)
459 res |= FILE_ATTRIBUTE_ARCHIVE_W;
460
461 //CB: not used: FILE_ATTRIBUTE_COMPRESSED_W
462
463 return res;
464}
465//******************************************************************************
466//******************************************************************************
467BOOL OSLibDosGetFileAttributesEx(PSZ pszName,
468 ULONG ulDummy,
469 PVOID pBuffer)
470{
471 APIRET rc; /* API return code */
472 FILESTATUS3 fs3; /* file information structure */
473 LPWIN32_FILE_ATTRIBUTE_DATA lpFad = (LPWIN32_FILE_ATTRIBUTE_DATA) pBuffer;
474
475 // Note: we only handle standard "GetFileExInfoStandard" requests
476 rc = DosQueryPathInfo(pszName, /* query the file information */
477 FIL_STANDARD,
478 &fs3,
479 sizeof(fs3));
480 if (rc != NO_ERROR) /* check for errors */
481 return FALSE; /* raise error condition */
482
483 // convert structure
484 lpFad->dwFileAttributes = pm2WinFileAttributes(fs3.attrFile);
485 pmDateTimeToFileTime(&fs3.fdateCreation, &fs3.ftimeCreation, &lpFad->ftCreationTime);
486 pmDateTimeToFileTime(&fs3.fdateLastAccess, &fs3.ftimeLastAccess, &lpFad->ftLastAccessTime);
487 pmDateTimeToFileTime(&fs3.fdateLastWrite, &fs3.ftimeLastWrite, &lpFad->ftLastWriteTime);
488
489 /* @@@PH we might add Aurora support ...
490 lpFad->nFileSizeHigh = info.nFileSizeHigh;
491 */
492 lpFad->nFileSizeHigh = 0;
493 lpFad->nFileSizeLow = fs3.cbFile;
494
495 return TRUE;
496}
497//******************************************************************************
498DWORD WIN32API GetEnvironmentVariableA(LPCSTR, LPSTR, DWORD );
499//******************************************************************************
500DWORD OSLibDosSearchPath(DWORD cmd, char *path, char *name, char *full_name,
501 DWORD length_fullname)
502{
503 switch(cmd) {
504 case OSLIB_SEARCHDIR:
505 if(DosSearchPath(SEARCH_IGNORENETERRS, path,
506 name, full_name, length_fullname) != 0) {
507 return 0;
508 }
509 return strlen(full_name);
510
511
512 case OSLIB_SEARCHCURDIR:
513 if(DosSearchPath(SEARCH_IGNORENETERRS | SEARCH_CUR_DIRECTORY, path,
514 name, full_name, length_fullname) != 0) {
515 return 0;
516 }
517 return strlen(full_name);
518
519 case OSLIB_SEARCHFILE:
520 {
521 FILESTATUS3 fileinfo;
522
523 if(DosQueryPathInfo(name, FIL_STANDARD, &fileinfo, sizeof(fileinfo)) != 0) {
524 return 0;
525 }
526 strncpy(full_name, name, length_fullname);
527 return strlen(full_name);
528 }
529
530 case OSLIB_SEARCHENV:
531 {
532 LPSTR envstring;
533 int envsize;
534 CHAR szResult[CCHMAXPATH];
535
536 envsize = GetEnvironmentVariableA(path, NULL, 0);
537 envstring = (LPSTR)malloc(envsize+1);
538 GetEnvironmentVariableA(path, envstring, envsize);
539 if(DosSearchPath(SEARCH_IGNORENETERRS, envstring,
540 name, szResult, sizeof(szResult)) != 0) {
541 free(envstring);
542 return 0;
543 }
544 free(envstring);
545 strcpy(full_name, szResult);
546 return strlen(full_name);
547 }
548 }
549 return 0;
550}
551//******************************************************************************
552//******************************************************************************
553DWORD OSLibDosCreate(CHAR *lpFileName,
554 DWORD dwAccess,
555 DWORD dwShare,
556 LPSECURITY_ATTRIBUTES lpSecurityAttributes,
557 DWORD dwCreation,
558 DWORD dwFlags,
559 HANDLE hTemplate,
560 DWORD *dwFile)
561{
562 APIRET rc;
563 HFILE hFile;
564 ULONG ulAction=0;
565 DWORD os2Attrib=0;
566 DWORD os2Flags = 0; //OPEN_FLAGS_NOINHERIT;
567 DWORD os2Open=0;
568
569 if(dwAccess == (GENERIC_READ_W | GENERIC_WRITE_W))
570 os2Flags |= OPEN_ACCESS_READWRITE;
571 else if(dwAccess & GENERIC_WRITE_W)
572 os2Flags |= OPEN_ACCESS_WRITEONLY;
573 else if(dwAccess & GENERIC_READ_W)
574 os2Flags |= OPEN_ACCESS_READONLY;
575
576 if(dwShare == 0)
577 os2Flags |= OPEN_SHARE_DENYREADWRITE;
578 else if(dwShare == (FILE_SHARE_READ_W | FILE_SHARE_WRITE_W))
579 os2Flags |= OPEN_SHARE_DENYNONE;
580 else if(dwShare & FILE_SHARE_READ_W)
581 os2Flags |= OPEN_SHARE_DENYWRITE;
582 else if(dwShare & FILE_SHARE_WRITE_W)
583 os2Flags |= OPEN_SHARE_DENYREAD;
584
585 if(dwCreation == CREATE_NEW_W)
586 os2Open = OPEN_ACTION_FAIL_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW;
587 else if(dwCreation == CREATE_ALWAYS_W)
588 os2Open = OPEN_ACTION_REPLACE_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW;
589 else if(dwCreation == OPEN_EXISTING_W)
590 os2Open = OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW;
591 else if(dwCreation == OPEN_ALWAYS_W)
592 os2Open = OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW;
593 else if(dwCreation == TRUNCATE_EXISTING_W)
594 os2Open = OPEN_ACTION_REPLACE_IF_EXISTS;// |OPEN_ACTION_FAIL_IF_NEW;
595
596 if(dwFlags & FILE_ATTRIBUTE_READONLY_W)
597 os2Attrib |= FILE_READONLY;
598 if(dwFlags & FILE_ATTRIBUTE_HIDDEN_W)
599 os2Attrib |= FILE_HIDDEN;
600 if(dwFlags & FILE_ATTRIBUTE_SYSTEM_W)
601 os2Attrib |= FILE_SYSTEM;
602 if(dwFlags & FILE_ATTRIBUTE_DIRECTORY_W)
603 os2Attrib |= FILE_DIRECTORY;
604 if(dwFlags & FILE_ATTRIBUTE_ARCHIVE_W)
605 os2Attrib |= FILE_ARCHIVED;
606 if(dwFlags & FILE_ATTRIBUTE_NORMAL_W)
607 os2Attrib |= FILE_NORMAL;
608
609 if(dwFlags & FILE_FLAG_WRITE_THROUGH_W)
610 os2Flags |= OPEN_FLAGS_WRITE_THROUGH;
611 if(dwFlags & FILE_FLAG_NO_BUFFERING_W)
612 os2Flags |= OPEN_FLAGS_NO_CACHE;
613 if(dwFlags & FILE_FLAG_RANDOM_ACCESS_W)
614 os2Flags |= OPEN_FLAGS_RANDOM;
615 if(dwFlags & FILE_FLAG_SEQUENTIAL_SCAN_W)
616 os2Flags |= OPEN_FLAGS_SEQUENTIAL;
617
618 // TODO:
619 // if(dwFlags & FILE_FLAG_OVERLAPPED_W)
620 // if(dwFlags & FILE_FLAG_DELETE_ON_CLOSE_W
621
622 rc = DosOpen(lpFileName, &hFile, &ulAction, 0,
623 os2Attrib, os2Open, os2Flags, 0);
624
625 if(rc)
626 {
627 // TODO: TEST TEST
628 dprintf(("DosOpen Error rc:%d, try without GENERIC_WRITE_W", rc));
629 if(dwAccess & GENERIC_WRITE_W)
630 os2Flags &= ~(OPEN_ACCESS_READWRITE | OPEN_ACCESS_WRITEONLY);
631 rc = DosOpen(lpFileName, &hFile, &ulAction, 0,
632 os2Attrib, os2Open, os2Flags, 0);
633 if(rc)
634 {
635 dprintf(("DosOpen Error rc:%d os2Attrib:%X os2Open:%X os2Flags:%X",
636 rc, os2Attrib, os2Open, os2Flags));
637 hFile = -1;
638 }
639 }
640
641 *dwFile = hFile;
642 return rc;
643}
644//******************************************************************************
645//(without changing file pointer)
646//******************************************************************************
647DWORD OSLibDosGetFileSize(DWORD hFile)
648{
649 FILESTATUS3 fsts3ConfigInfo = {{0}};
650 ULONG ulBufSize = sizeof(FILESTATUS3);
651
652 DosQueryFileInfo(hFile, FIL_STANDARD, &fsts3ConfigInfo, ulBufSize);
653 return fsts3ConfigInfo.cbFile;
654}
655//******************************************************************************
656//******************************************************************************
657DWORD OSLibDosSetFilePtr2(DWORD hFile, DWORD offset, DWORD method)
658{
659 DWORD newoffset;
660 APIRET rc;
661
662
663 rc = DosSetFilePtr(hFile, offset, method, &newoffset);
664 if(rc) {
665 dprintf(("DosSetFilePtr Error rc:%d", rc));
666 return -1;
667 }
668 else return newoffset;
669}
670//******************************************************************************
671//(FlushBuffer)
672//******************************************************************************
673DWORD OSLibDosResetBuffer(DWORD hFile)
674{
675 return DosResetBuffer(hFile);
676}
677//******************************************************************************
678//******************************************************************************
679DWORD OSLibDosDupHandle(DWORD hFile, DWORD *hNew)
680{
681 *hNew = -1;
682 return DosDupHandle(hFile, hNew);
683}
684//******************************************************************************
685//******************************************************************************
686void OSLibDosDisableHardError(BOOL fTurnOff)
687{
688 DosError((fTurnOff) ? FERR_DISABLEHARDERR : FERR_ENABLEHARDERR);
689}
690//******************************************************************************
691//Returns time spent in kernel & user mode in milliseconds
692//******************************************************************************
693BOOL OSLibDosQueryProcTimes(DWORD procid, ULONG *kerneltime, ULONG *usertime)
694{
695 APIRET rc;
696 char *buf;
697 ULONG size;
698 ULONG nrthreads = 4;
699
700tryagain:
701 size = sizeof(QTOPLEVEL)+sizeof(QGLOBAL)+sizeof(QPROCESS) + nrthreads*sizeof(QTHREAD);
702 buf = (char *)malloc(size);
703 rc = DosQuerySysState(0x1, RESERVED, procid, RESERVED, (PCHAR)buf, size);
704
705 if(rc) {
706 free(buf);
707 if(rc == ERROR_BUFFER_OVERFLOW) {
708 nrthreads += 4;
709 goto tryagain;
710 }
711 return FALSE;
712 }
713 PQTOPLEVEL top = (PQTOPLEVEL)buf;
714
715 *kerneltime = 0;
716 *usertime = 0;
717 for(int i=0;i<top->procdata->threadcnt;i++) {
718 *kerneltime += top->procdata->threads[i].systime;
719 *usertime += top->procdata->threads[i].usertime;
720 }
721 free(buf);
722 return TRUE;
723}
724//******************************************************************************
725//******************************************************************************
726// TODO: implement SecurityAttributes parameter
727DWORD OSLibDosCreateNamedPipe(LPCTSTR lpName,
728 DWORD dwOpenMode,
729 DWORD dwPipeMode,
730 DWORD nMaxInstances,
731 DWORD nOutBufferSize,
732 DWORD nInBufferSize,
733 DWORD nDefaultTimeOut,
734 void* lpSecurityAttributes)
735{ DWORD dwOS2Mode = 0;
736 DWORD dwOS2PipeMode = 0;
737 LPSTR lpOS2Name;
738 DWORD hPipe;
739 DWORD rc;
740
741 if (dwOpenMode & PIPE_ACCESS_DUPLEX_W)
742 dwOS2Mode |= NP_ACCESS_DUPLEX;
743 else
744 if (dwOpenMode & PIPE_ACCESS_INBOUND_W)
745 dwOS2Mode |= NP_ACCESS_INBOUND;
746 else
747 if (dwOpenMode & PIPE_ACCESS_OUTBOUND_W)
748 dwOS2Mode |= NP_ACCESS_OUTBOUND;
749 // TODO:
750 // if(dwOpenMode & FILE_FLAG_OVERLAPPED)
751 // if(dwOpenMode & WRITE_DAC)
752 // if(dwOpenMode & WRITE_OWNER)
753 // if(dwOpenMode & ACCESS_SYSTEM_SECURITY)
754 if(dwOpenMode & FILE_FLAG_WRITE_THROUGH_W)
755 dwOS2Mode |= NP_WRITEBEHIND; // FIXME: I'm not sure!
756
757 if (dwPipeMode & PIPE_WAIT_W)
758 dwOS2PipeMode |= NP_WAIT;
759 if (dwPipeMode & PIPE_NOWAIT_W)
760 dwOS2PipeMode |= NP_NOWAIT;
761 if (dwPipeMode & PIPE_READMODE_BYTE_W)
762 dwOS2PipeMode |= NP_READMODE_BYTE;
763 if (dwPipeMode & PIPE_READMODE_MESSAGE_W)
764 dwOS2PipeMode |= NP_READMODE_MESSAGE;
765 if (dwPipeMode & PIPE_TYPE_BYTE_W)
766 dwOS2PipeMode |= NP_TYPE_BYTE;
767 if (dwPipeMode & PIPE_TYPE_MESSAGE_W)
768 dwOS2PipeMode |= NP_TYPE_MESSAGE;
769
770 if (nMaxInstances>0xff)
771 {
772 SetLastError(ERROR_INVALID_PARAMETER_W); // ERROR_INVALID_PARAMETER
773 return -1; // INVALID_HANDLE_VALUE
774 }
775 dwOS2PipeMode |= nMaxInstances;
776
777 if (strstr(lpName,"\\\\."))
778 {
779 // If pipe is created on the local machine
780 // we must delete string \\. because
781 // in Windows named pipes scheme is a \\.\PIPE\pipename
782 // but in OS/2 only \PIPE\pipename
783 lpOS2Name = (LPSTR)lpName + 3;
784 }
785 else lpOS2Name = (LPSTR)lpName;
786
787 dprintf(("DosCreateNPipe(%s,%x,%x,%x,%x,%x)",lpOS2Name,dwOS2Mode,dwOS2PipeMode,nInBufferSize,nOutBufferSize,nDefaultTimeOut));
788 rc=DosCreateNPipe(lpOS2Name,
789 &hPipe,
790 dwOS2Mode,
791 dwOS2PipeMode,
792 nInBufferSize,
793 nInBufferSize,
794 nDefaultTimeOut); // Timeouts must be tested!
795
796 dprintf(("DosCreateNPipe rc=%d",rc));
797 if (rc)
798 {
799 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER_W));
800 return -1; // INVALID_HANDLE_VALUE
801 }
802 return hPipe;
803}
804
805//******************************************************************************
806//******************************************************************************
807// TODO: implement lpOverlapped parameter!
808BOOL OSLibDosConnectNamedPipe(DWORD hNamedPipe, LPOVERLAPPED lpOverlapped)
809{
810 DWORD rc;
811
812 rc=DosConnectNPipe(hNamedPipe);
813 dprintf(("DosConnectNPipe rc=%d",rc));
814
815 if (!rc) return (TRUE);
816 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
817
818 return (FALSE);
819}
820
821//******************************************************************************
822//******************************************************************************
823BOOL OSLibDosCallNamedPipe( LPCTSTR lpNamedPipeName,
824 LPVOID lpInBuffer,
825 DWORD nInBufferSize,
826 LPVOID lpOutBuffer,
827 DWORD nOutBufferSize,
828 LPDWORD lpBytesRead,
829 DWORD nTimeOut )
830{
831 LPSTR lpOS2Name;
832 DWORD rc;
833
834 if (strstr(lpNamedPipeName,"\\\\."))
835 {
836 // If pipe is created on the local machine
837 // we must delete string \\. because
838 // in Windows named pipes scheme is a \\.\PIPE\pipename
839 // but in OS/2 only \PIPE\pipename
840 lpOS2Name = (LPSTR)lpNamedPipeName + 3;
841 }
842 else lpOS2Name = (LPSTR)lpNamedPipeName;
843
844 rc=DosCallNPipe(lpOS2Name,
845 lpInBuffer,
846 nInBufferSize,
847 lpOutBuffer,
848 nOutBufferSize,
849 lpBytesRead,
850 nTimeOut );
851
852
853 if (!rc) return (TRUE);
854 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
855
856 return (FALSE);
857}
858
859//******************************************************************************
860//******************************************************************************
861BOOL OSLibDosTransactNamedPipe( DWORD hNamedPipe,
862 LPVOID lpInBuffer,
863 DWORD nInBufferSize,
864 LPVOID lpOutBuffer,
865 DWORD nOutBufferSize,
866 LPDWORD lpBytesRead,
867 LPOVERLAPPED lpOverlapped)
868{
869 DWORD rc;
870
871 rc=DosTransactNPipe(hNamedPipe,
872 lpOutBuffer,
873 nOutBufferSize,
874 lpInBuffer,
875 nInBufferSize,
876 lpBytesRead);
877
878 dprintf(("DosTransactNPipe returned rc=%d");)
879 if (!rc) return (TRUE);
880 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
881
882 return (FALSE);
883}
884
885//******************************************************************************
886//******************************************************************************
887BOOL OSLibDosPeekNamedPipe(DWORD hPipe,
888 LPVOID lpvBuffer,
889 DWORD cbBuffer,
890 LPDWORD lpcbRead,
891 LPDWORD lpcbAvail,
892 LPDWORD lpcbMessage)
893{
894 DWORD rc;
895 AVAILDATA availData ={0};
896 ULONG ulDummy;
897
898 rc=DosPeekNPipe(hPipe,lpvBuffer,cbBuffer,lpcbRead,&availData,&ulDummy);
899
900 dprintf(("DosPeekNPipe returned rc=%d",rc));
901
902 if (!rc)
903 {
904 *lpcbAvail = availData.cbpipe;
905 *lpcbMessage = availData.cbmessage;
906 return (TRUE);
907 }
908 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
909
910 return (FALSE);
911}
912//******************************************************************************
913//******************************************************************************
914BOOL OSLibDosDisconnectNamedPipe(DWORD hPipe)
915{
916 DWORD rc;
917
918 rc=DosDisConnectNPipe(hPipe);
919
920 dprintf(("DosDisConnectNPipe returned rc=%d",rc));
921
922 if (!rc) return TRUE;
923 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
924
925 return (FALSE);
926}
927//******************************************************************************
928//******************************************************************************
929BOOL OSLibDosWaitNamedPipe(LPCSTR lpszNamedPipeName,
930 DWORD dwTimeout)
931{
932 LPSTR lpOS2Name;
933 DWORD rc;
934
935 if (strstr(lpszNamedPipeName,"\\\\."))
936 {
937 // If pipe is created on the local machine
938 // we must delete string \\. because
939 // in Windows named pipes scheme is a \\.\PIPE\pipename
940 // but in OS/2 only \PIPE\pipename
941 lpOS2Name = (LPSTR)lpszNamedPipeName + 3;
942 }
943 else lpOS2Name = (LPSTR)lpszNamedPipeName;
944
945 rc=DosWaitNPipe(lpOS2Name,dwTimeout);
946
947 dprintf(("DosWaitNPipe returned rc=%d",rc));
948
949 if (!rc) return TRUE;
950 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
951
952 return (FALSE);
953}
954//******************************************************************************
955//******************************************************************************
956BOOL isRoot(CHAR* name)
957{
958 if (name[1] == ':')
959 {
960 //local name (x:\)
961 return (name[2] == 0) || !strchr(&name[3],'\\');
962 } else if (name[0] == '\\')
963 {
964 //UNC name (\\resource\drive\)
965 CHAR *drive,*dir;
966
967 drive = strchr(&name[2],'\\');
968 if (!drive) return FALSE;
969 dir = strchr(&drive[1],'\\');
970 if (!dir) return TRUE;
971 return !strchr(&dir[1],'\\');
972 } else return FALSE; //unknown
973}
974//******************************************************************************
975//******************************************************************************
976inline CHAR system2DOSCharacter(CHAR ch)
977{
978 switch(ch)
979 {
980 case ' ':
981 case '.':
982 case '~':
983 return '_';
984
985 default:
986 return toupper(ch);
987 }
988}
989
990VOID long2ShortName(CHAR* longName,CHAR* shortName)
991{
992 INT x;
993 CHAR *source = longName,*dest = shortName,*ext = strrchr(longName,'.');
994
995 if ((strcmp(longName,".") == 0) || (strcmp(longName,"..") == 0))
996 {
997 strcpy(shortName,longName);
998 return;
999 }
1000
1001 //CB: quick and dirty, real FILE~12.EXT is too slow
1002
1003 //8 character file name
1004 for (x = 0;x < 8;x++)
1005 {
1006 if ((source == ext) || (source[0] == 0)) break;
1007 dest[0] = system2DOSCharacter(source[0]);
1008 source++;
1009 dest++;
1010 }
1011
1012 if (source[0] == 0)
1013 {
1014 dest[0] = 0;
1015 return;
1016 }
1017
1018 if (source != ext)
1019 {
1020 //longName > 8 characters, insert ~1
1021 shortName[6] = '~';
1022 shortName[7] = '1';
1023 }
1024
1025 if (ext)
1026 {
1027 //add extension, 3 characters
1028 dest[0] = ext[0];
1029 dest++;
1030 ext++;
1031 for (x = 0;x < 3;x++)
1032 {
1033 if (ext[0] == 0) break;
1034 dest[0] = system2DOSCharacter(ext[0]);
1035 ext++;
1036 dest++;
1037 }
1038 }
1039 dest[0] = 0;
1040}
1041//******************************************************************************
1042//******************************************************************************
1043VOID translateFileResults(FILESTATUS3 *pResult,LPWIN32_FIND_DATAA pFind,CHAR* achName)
1044{
1045 CHAR* name;
1046
1047 pFind->dwFileAttributes = pm2WinFileAttributes(pResult->attrFile);
1048
1049 pmDateTimeToFileTime(&pResult->fdateCreation,&pResult->ftimeCreation,&pFind->ftCreationTime);
1050 pmDateTimeToFileTime(&pResult->fdateLastAccess,&pResult->ftimeLastAccess,&pFind->ftLastAccessTime);
1051 pmDateTimeToFileTime(&pResult->fdateLastWrite,&pResult->ftimeLastWrite,&pFind->ftLastWriteTime);
1052
1053 pFind->nFileSizeHigh = 0; //CB: fixme
1054 pFind->nFileSizeLow = pResult->cbFile;
1055 name = strrchr(achName,'\\');
1056 if (name)
1057 {
1058 name++;
1059 strcpy(pFind->cFileName,name);
1060 } else pFind->cFileName[0] = 0;
1061 long2ShortName(pFind->cFileName,pFind->cAlternateFileName);
1062}
1063
1064VOID translateFindResults(FILEFINDBUF3 *pResult,LPWIN32_FIND_DATAA pFind)
1065{
1066 pFind->dwFileAttributes = pm2WinFileAttributes(pResult->attrFile);
1067
1068 pmDateTimeToFileTime(&pResult->fdateCreation,&pResult->ftimeCreation,&pFind->ftCreationTime);
1069 pmDateTimeToFileTime(&pResult->fdateLastAccess,&pResult->ftimeLastAccess,&pFind->ftLastAccessTime);
1070 pmDateTimeToFileTime(&pResult->fdateLastWrite,&pResult->ftimeLastWrite,&pFind->ftLastWriteTime);
1071
1072 pFind->nFileSizeHigh = 0; //CB: fixme
1073 pFind->nFileSizeLow = pResult->cbFile;
1074 strcpy(pFind->cFileName,pResult->achName);
1075 long2ShortName(pFind->cFileName,pFind->cAlternateFileName);
1076}
1077//******************************************************************************
1078//******************************************************************************
1079DWORD OSLibDosFindFirst(LPCSTR lpFileName,WIN32_FIND_DATAA* lpFindFileData)
1080{
1081 HDIR hDir = -1;
1082 ULONG attrs;
1083 FILEFINDBUF3 result;
1084 ULONG searchCount = 1;
1085
1086 attrs = FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY | FILE_ARCHIVED;
1087 result.achName[0] = 0;
1088
1089 DosError(FERR_DISABLEHARDERR | FERR_DISABLEEXCEPTION);
1090 APIRET rc = DosFindFirst((PSZ)lpFileName,&hDir,attrs,&result,sizeof(result),&searchCount,FIL_STANDARD);
1091 DosError(FERR_ENABLEHARDERR | FERR_ENABLEEXCEPTION);
1092
1093 //check root: skip "." and ".." (HPFS, not on FAT)
1094 //check in OSLibDosFindNext not necessary: "." and ".." are the first two entries
1095 if ((rc == 0) && isRoot((LPSTR)lpFileName))
1096 {
1097 while ((strcmp(result.achName,".") == 0) || (strcmp(result.achName,"..") == 0))
1098 {
1099 result.achName[0] = 0;
1100 DosError(FERR_DISABLEHARDERR | FERR_DISABLEEXCEPTION);
1101 searchCount = 1;
1102 APIRET rc = DosFindNext(hDir,&result,sizeof(result),&searchCount);
1103 DosError(FERR_ENABLEHARDERR | FERR_ENABLEEXCEPTION);
1104 if (rc)
1105 {
1106 DosFindClose(hDir);
1107 SetLastError(error2WinError(rc));
1108
1109 return INVALID_HANDLE_VALUE_W;
1110 }
1111 }
1112 }
1113 if(rc) {
1114 DosFindClose(hDir);
1115 SetLastError(error2WinError(rc));
1116 return INVALID_HANDLE_VALUE_W;
1117 }
1118 translateFindResults(&result,lpFindFileData);
1119 return hDir;
1120}
1121//******************************************************************************
1122// NOTE: returns "." and ".." in root
1123//******************************************************************************
1124DWORD OSLibDosFindFirstMulti(LPCSTR lpFileName,WIN32_FIND_DATAA *lpFindFileData,DWORD *count)
1125{
1126 HDIR hDir = -1;
1127 ULONG attrs;
1128 FILEFINDBUF3 *result,*data;
1129 ULONG searchCount = *count;
1130
1131 attrs = FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY | FILE_ARCHIVED;
1132 result = (FILEFINDBUF3*)malloc(searchCount*sizeof(FILEFINDBUF3));
1133
1134 DosError(FERR_DISABLEHARDERR | FERR_DISABLEEXCEPTION);
1135 APIRET rc = DosFindFirst((PSZ)lpFileName,&hDir,attrs,result,searchCount*sizeof(FILEFINDBUF3),&searchCount,FIL_STANDARD);
1136 DosError(FERR_ENABLEHARDERR | FERR_ENABLEEXCEPTION);
1137 if (rc)
1138 {
1139 free(result);
1140 *count = 0;
1141 SetLastError(error2WinError(rc));
1142
1143 return INVALID_HANDLE_VALUE_W;
1144 }
1145
1146 data = result;
1147 for (int x = 0;x < searchCount;x++)
1148 {
1149 translateFindResults(data,&lpFindFileData[x]);
1150 data = (FILEFINDBUF3*)(((DWORD)data)+data->oNextEntryOffset);
1151 }
1152 free(result);
1153 *count = searchCount;
1154
1155 return hDir;
1156}
1157//******************************************************************************
1158//******************************************************************************
1159BOOL OSLibDosFindNext(DWORD hFindFile,WIN32_FIND_DATAA *lpFindFileData)
1160{
1161 FILEFINDBUF3 result;
1162 ULONG searchCount = 1;
1163
1164 APIRET rc = DosFindNext((HDIR)hFindFile,&result,sizeof(result),&searchCount);
1165 if (rc)
1166 {
1167 SetLastError(error2WinError(rc));
1168
1169 return FALSE;
1170 }
1171
1172 translateFindResults(&result,lpFindFileData);
1173
1174 return TRUE;
1175}
1176//******************************************************************************
1177//******************************************************************************
1178BOOL OSLibDosFindNextMulti(DWORD hFindFile,WIN32_FIND_DATAA *lpFindFileData,DWORD *count)
1179{
1180 FILEFINDBUF3 *result,*data;
1181 ULONG searchCount = *count;
1182
1183 result = (FILEFINDBUF3*)malloc(searchCount*sizeof(FILEFINDBUF3));
1184 APIRET rc = DosFindNext((HDIR)hFindFile,result,searchCount*sizeof(FILEFINDBUF3),&searchCount);
1185 if (rc)
1186 {
1187 free(result);
1188 *count = 0;
1189 SetLastError(error2WinError(rc));
1190
1191 return FALSE;
1192 }
1193
1194 data = result;
1195 for (int x = 0;x < searchCount;x++)
1196 {
1197 translateFindResults(data,&lpFindFileData[x]);
1198 data = (FILEFINDBUF3*)(((DWORD)data)+data->oNextEntryOffset);
1199 }
1200 free(result);
1201 *count = searchCount;
1202
1203 return TRUE;
1204}
1205//******************************************************************************
1206//******************************************************************************
1207BOOL OSLibDosFindClose(DWORD hFindFile)
1208{
1209 APIRET rc = DosFindClose((HDIR)hFindFile);
1210 if (rc)
1211 {
1212 SetLastError(error2WinError(rc));
1213
1214 return FALSE;
1215 }
1216
1217 return TRUE;
1218}
Note: See TracBrowser for help on using the repository browser.