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

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

.

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