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

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

.

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