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

Last change on this file since 6850 was 6850, checked in by phaller, 24 years ago

further error mappings

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