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

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

semaphore updates

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