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

Last change on this file since 6029 was 6029, checked in by sandervl, 24 years ago

disk updates

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