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

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

minor updates

File size: 86.7 KB
Line 
1/* $Id: oslibdos.cpp,v 1.81 2001-10-29 20:08:40 sandervl Exp $ */
2/*
3 * Wrappers for OS/2 Dos* API
4 *
5 * Copyright 1998-2000 Sander van Leeuwen (sandervl@xs4all.nl)
6 * Copyright 1999-2000 Edgar Buerkle (Edgar.Buerkle@gmx.net)
7 * Copyright 2000 Przemyslaw Dobrowolski (dobrawka@asua.org.pl)
8 * Copyright 2000 Christoph Bratschi (cbratschi@datacomm.ch)
9 * Copyright 2000 knut st. osmundsen (knut.stange.osmundsen@mynd.no)
10 *
11 * Project Odin Software License can be found in LICENSE.TXT
12 *
13 */
14#define INCL_BASE
15#define INCL_DOSEXCEPTIONS
16#define INCL_DOSMEMMGR
17#define INCL_DOSPROCESS
18#define INCL_DOSFILEMGR
19#define INCL_DOSERRORS
20#define INCL_DOSDEVIOCTL
21#define INCL_NPIPES
22#include <os2wrap.h> //Odin32 OS/2 api wrappers
23#include <stdlib.h>
24#include <stdio.h>
25#include <string.h>
26#include <ctype.h>
27#include <win32api.h>
28#include <winconst.h>
29#include <win\winioctl.h>
30#include <misc.h>
31#include "initterm.h"
32#include "oslibdos.h"
33#include "dosqss.h"
34#include "win32k.h"
35
36#define DBG_LOCALLOG DBG_oslibdos
37#include "dbglocal.h"
38
39static PROC_DosSetFileSizeL DosSetFileSizeLProc = 0;
40static PROC_DosSetFilePtrL DosSetFilePtrLProc = 0;
41static PROC_DosSetFileLocksL DosSetFileLocksLProc = 0;
42static BOOL f64BitIO = FALSE;
43//******************************************************************************
44//******************************************************************************
45void OSLibInitWSeBFileIO()
46{
47 HMODULE hDoscalls;
48
49 if(DosQueryModuleHandle("DOSCALLS", &hDoscalls) != NO_ERROR) {
50 return;
51 }
52 if(DosQueryProcAddr(hDoscalls, 989, NULL, (PFN *)&DosSetFileSizeLProc) != NO_ERROR) {
53 return;
54 }
55 if(DosQueryProcAddr(hDoscalls, 988, NULL, (PFN *)&DosSetFilePtrLProc) != NO_ERROR) {
56 return;
57 }
58 if(DosQueryProcAddr(hDoscalls, 986, NULL, (PFN *)&DosSetFileLocksLProc) != NO_ERROR) {
59 return;
60 }
61 f64BitIO = TRUE;
62}
63//******************************************************************************
64//******************************************************************************
65APIRET OdinDosSetFileSizeL(HFILE hFile, LONGLONG cbSize)
66{
67 APIRET yyrc;
68 USHORT sel = RestoreOS2FS();
69
70 yyrc = DosSetFileSizeLProc(hFile, cbSize);
71 SetFS(sel);
72
73 return yyrc;
74}
75//******************************************************************************
76//******************************************************************************
77APIRET OdinDosSetFilePtrL(HFILE hFile, LONGLONG ib, ULONG method, PLONGLONG ibActual)
78{
79 APIRET yyrc;
80 USHORT sel = RestoreOS2FS();
81
82 yyrc = DosSetFilePtrLProc(hFile, ib, method, ibActual);
83 SetFS(sel);
84
85 return yyrc;
86}
87//******************************************************************************
88//******************************************************************************
89APIRET OdinDosSetFileLocksL(HFILE hFile, PFILELOCKL pflUnlock, PFILELOCKL pflLock,
90 ULONG timeout, ULONG flags)
91{
92 APIRET yyrc;
93 USHORT sel = RestoreOS2FS();
94
95 yyrc = DosSetFileLocksLProc(hFile, pflUnlock, pflLock, timeout, flags);
96 SetFS(sel);
97
98 return yyrc;
99}
100//******************************************************************************
101// translate OS/2 error codes to Windows codes
102// NOTE: add all codes you need, list is not complete!
103//******************************************************************************
104DWORD error2WinError(APIRET rc,DWORD defaultCode)
105{
106 switch (rc)
107 {
108 case NO_ERROR: //0
109 return ERROR_SUCCESS_W;
110
111 case ERROR_INVALID_FUNCTION: //1
112 return ERROR_INVALID_FUNCTION_W;
113
114 case ERROR_FILE_NOT_FOUND: //2
115 return ERROR_FILE_NOT_FOUND_W;
116
117 case ERROR_PATH_NOT_FOUND: //3
118 return ERROR_PATH_NOT_FOUND_W;
119
120 case ERROR_TOO_MANY_OPEN_FILES: //4
121 return ERROR_TOO_MANY_OPEN_FILES_W;
122
123 case ERROR_ACCESS_DENIED: //5
124 return ERROR_ACCESS_DENIED_W;
125
126 case ERROR_INVALID_HANDLE: //6
127 return ERROR_INVALID_HANDLE_W;
128
129 case ERROR_NOT_ENOUGH_MEMORY: //8
130 return ERROR_NOT_ENOUGH_MEMORY_W;
131
132 case ERROR_BAD_FORMAT: //11
133 return ERROR_BAD_FORMAT_W;
134
135 case ERROR_INVALID_ACCESS: //12
136 return ERROR_INVALID_ACCESS_W;
137
138 case ERROR_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 SetLastError(ERROR_SUCCESS_W);
735 return newoffset;
736}
737//******************************************************************************
738//******************************************************************************
739BOOL OSLibDosDelete(char *lpszFileName)
740{
741 APIRET rc;
742
743 rc = DosDelete(lpszFileName);
744 if(rc) {
745 SetLastError(error2WinError(rc));
746 return FALSE;
747 }
748 return TRUE;
749}
750//******************************************************************************
751//******************************************************************************
752BOOL pmDateTimeToFileTime(FDATE *pDate,FTIME *pTime,FILETIME *pFT)
753{
754 register USHORT dosTime, dosDate;
755
756 dosTime = *(USHORT*)pTime;
757 dosDate = *(USHORT*)pDate;
758
759 // PH: probably replace with faster implementation than calling Open32
760 // through the external interface!
761 return DosDateTimeToFileTime(dosDate,dosTime,pFT);
762}
763//******************************************************************************
764//******************************************************************************
765#define NOT_NORMAL (FILE_ATTRIBUTE_READONLY_W | \
766 FILE_ATTRIBUTE_HIDDEN_W | \
767 FILE_ATTRIBUTE_SYSTEM_W | \
768 FILE_ATTRIBUTE_ARCHIVE_W)
769
770inline DWORD pm2WinFileAttributes(DWORD attrFile)
771{
772 DWORD res = 0;
773
774 if (!(attrFile & NOT_NORMAL))
775 res |= FILE_ATTRIBUTE_NORMAL_W;
776 if (attrFile & FILE_READONLY)
777 res |= FILE_ATTRIBUTE_READONLY_W;
778 if (attrFile & FILE_HIDDEN)
779 res |= FILE_ATTRIBUTE_HIDDEN_W;
780 if (attrFile & FILE_SYSTEM)
781 res |= FILE_ATTRIBUTE_SYSTEM_W;
782 if (attrFile & FILE_DIRECTORY)
783 res |= FILE_ATTRIBUTE_DIRECTORY_W;
784 if (attrFile & FILE_ARCHIVED)
785 res |= FILE_ATTRIBUTE_ARCHIVE_W;
786
787 //CB: not used: FILE_ATTRIBUTE_COMPRESSED_W
788 //PH: NT server will serve appropriate sizes for compressed files
789 // over network. So if realSize < allocatedSize, the file must
790 // be compressed.
791
792 return res;
793}
794//******************************************************************************
795//******************************************************************************
796BOOL OSLibDosGetFileAttributesEx(PSZ pszName,
797 ULONG ulDummy,
798 PVOID pBuffer)
799{
800 APIRET rc; /* API return code */
801 FILESTATUS3 fs3; /* file information structure */
802 LPWIN32_FILE_ATTRIBUTE_DATA lpFad = (LPWIN32_FILE_ATTRIBUTE_DATA) pBuffer;
803
804 // Note: we only handle standard "GetFileExInfoStandard" requests
805 rc = DosQueryPathInfo(pszName, /* query the file information */
806 FIL_STANDARD,
807 &fs3,
808 sizeof(fs3));
809 if (rc != NO_ERROR) /* check for errors */
810 return FALSE; /* raise error condition */
811
812 // convert structure
813 lpFad->dwFileAttributes = pm2WinFileAttributes(fs3.attrFile);
814 pmDateTimeToFileTime(&fs3.fdateCreation, &fs3.ftimeCreation, &lpFad->ftCreationTime);
815 pmDateTimeToFileTime(&fs3.fdateLastAccess, &fs3.ftimeLastAccess, &lpFad->ftLastAccessTime);
816 pmDateTimeToFileTime(&fs3.fdateLastWrite, &fs3.ftimeLastWrite, &lpFad->ftLastWriteTime);
817
818 /* @@@PH we might add Aurora support ...
819 lpFad->nFileSizeHigh = info.nFileSizeHigh;
820 */
821 lpFad->nFileSizeHigh = 0;
822 lpFad->nFileSizeLow = fs3.cbFile;
823
824 return TRUE;
825}
826//******************************************************************************
827DWORD WIN32API GetEnvironmentVariableA(LPCSTR, LPSTR, DWORD );
828//******************************************************************************
829DWORD OSLibDosSearchPath(DWORD cmd, char *path, char *name, char *full_name,
830 DWORD length_fullname)
831{
832 switch(cmd) {
833 case OSLIB_SEARCHDIR:
834 if(DosSearchPath(SEARCH_IGNORENETERRS, path,
835 name, full_name, length_fullname) != 0) {
836 return 0;
837 }
838 return strlen(full_name);
839
840
841 case OSLIB_SEARCHCURDIR:
842 if(DosSearchPath(SEARCH_IGNORENETERRS | SEARCH_CUR_DIRECTORY, path,
843 name, full_name, length_fullname) != 0) {
844 return 0;
845 }
846 return strlen(full_name);
847
848 case OSLIB_SEARCHFILE:
849 {
850 FILESTATUS3 fileinfo;
851
852 if(DosQueryPathInfo(name, FIL_STANDARD, &fileinfo, sizeof(fileinfo)) != 0) {
853 return 0;
854 }
855 strncpy(full_name, name, length_fullname);
856 full_name[length_fullname-1] = 0;
857 return strlen(full_name);
858 }
859
860 case OSLIB_SEARCHENV:
861 {
862 LPSTR envstring;
863 int envsize;
864 CHAR szResult[CCHMAXPATH];
865
866 envsize = GetEnvironmentVariableA(path, NULL, 0);
867 envstring = (LPSTR)malloc(envsize+1);
868 GetEnvironmentVariableA(path, envstring, envsize);
869 if(DosSearchPath(SEARCH_IGNORENETERRS, envstring,
870 name, szResult, sizeof(szResult)) != 0) {
871 free(envstring);
872 return 0;
873 }
874 free(envstring);
875 strcpy(full_name, szResult);
876 return strlen(full_name);
877 }
878 }
879 return 0;
880}
881//******************************************************************************
882//******************************************************************************
883DWORD OSLibDosQueryPathInfo(CHAR *pszPathName,
884 ULONG ulInfoLevel,
885 PVOID pInfoBuf,
886 ULONG cbInfoBuf)
887{
888 APIRET rc = DosQueryPathInfo( pszPathName, ulInfoLevel,
889 pInfoBuf, cbInfoBuf );
890
891 if(rc == ERROR_TOO_MANY_OPEN_FILES)
892 {
893 LONG reqCount = 2;
894 ULONG maxFiles;
895
896 if(DosSetRelMaxFH(&reqCount, &maxFiles) == NO_ERROR)
897 rc = DosQueryPathInfo(pszPathName, ulInfoLevel,
898 pInfoBuf, cbInfoBuf );
899 }
900 return rc;
901}
902//******************************************************************************
903//******************************************************************************
904DWORD OSLibDosCreateFile(CHAR *lpszFile,
905 DWORD fuAccess,
906 DWORD fuShare,
907 LPSECURITY_ATTRIBUTES lpSecurityAttributes,
908 DWORD fuCreate,
909 DWORD fuAttrFlags,
910 HANDLE hTemplateFile)
911{
912 HFILE hFile;
913 ULONG actionTaken = 0;
914 ULONG fileSize = 0;
915 ULONG fileAttr = FILE_NORMAL;
916 ULONG openFlag = 0;
917 ULONG openMode = 0;
918 APIRET rc = ERROR_NOT_ENOUGH_MEMORY;;
919
920 //TODO: lpSecurityAttributes (inheritance)
921
922 if(fuAttrFlags & FILE_ATTRIBUTE_ARCHIVE_W)
923 fileAttr |= FILE_ARCHIVED;
924 if(fuAttrFlags & FILE_ATTRIBUTE_HIDDEN_W)
925 fileAttr |= FILE_HIDDEN;
926 if(fuAttrFlags & FILE_ATTRIBUTE_SYSTEM_W)
927 fileAttr |= FILE_SYSTEM;
928 if(fuAttrFlags & FILE_ATTRIBUTE_READONLY_W)
929 fileAttr |= FILE_READONLY;
930 // TODO: FILE_ATTRIBUTE_TEMPORARY_W
931
932 switch(fuCreate)
933 {
934 case CREATE_NEW_W:
935 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_FAIL_IF_EXISTS;
936 break;
937 case CREATE_ALWAYS_W:
938 /* kso 2000-11-26: Not sure if OPEN_ACTION_REPLACE_IF_EXISTS is correct here! It is correct according to
939 * MSDN, but not according to "The Win32 API SuperBible". Anyway I haven't got time to check it out in
940 * NT now.
941 * The problem is that OPEN_ACTION_REPLACE_IF_EXISTS requires write access. It failes with
942 * rc = ERROR_ACCESS_DENIED (5). Quick fix, use OPEN_IF_EXIST if readonly access.
943 */
944 if (fuAccess & GENERIC_WRITE_W)
945 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS;
946 else
947 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
948 break;
949 case OPEN_EXISTING_W:
950 openFlag |= OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
951 break;
952 case OPEN_ALWAYS_W:
953 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
954 break;
955 case TRUNCATE_EXISTING_W:
956 openFlag |= OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS;
957 break;
958 }
959
960 if(fuAttrFlags & FILE_FLAG_WRITE_THROUGH_W) openMode |= OPEN_FLAGS_WRITE_THROUGH;
961 if(fuAttrFlags & FILE_FLAG_NO_BUFFERING_W) openMode |= OPEN_FLAGS_NO_CACHE;
962 if(fuAttrFlags & FILE_FLAG_RANDOM_ACCESS_W) openMode |= OPEN_FLAGS_RANDOM;
963 if(fuAttrFlags & FILE_FLAG_SEQUENTIAL_SCAN_W) openMode |= OPEN_FLAGS_SEQUENTIAL;
964 // TODO: FILE_FLAG_BACKUP_SEMANTICS_W
965 // FILE_FLAG_POSIX_SEMANTICS_W are not supported
966
967 //TODO: FILE_SHARE_DELETE
968 if((fuShare & (FILE_SHARE_READ_W | FILE_SHARE_WRITE_W)) == 0 )
969 openMode |= OPEN_SHARE_DENYREADWRITE;
970 else
971 if((fuShare & (FILE_SHARE_READ_W | FILE_SHARE_WRITE_W)) == (FILE_SHARE_READ_W | FILE_SHARE_WRITE_W))
972 openMode |= OPEN_SHARE_DENYNONE;
973 else
974 if(fuShare & FILE_SHARE_READ_W)
975 openMode |= OPEN_SHARE_DENYWRITE;
976 else
977 if(fuShare & FILE_SHARE_WRITE_W)
978 openMode |= OPEN_SHARE_DENYREAD;
979
980 if(fuAccess == (GENERIC_READ_W | GENERIC_WRITE_W))
981 openMode |= OPEN_ACCESS_READWRITE;
982 else
983 if(fuAccess & GENERIC_READ_W)
984 openMode |= OPEN_ACCESS_READONLY;
985 else
986 if(fuAccess & GENERIC_WRITE_W)
987 openMode |= OPEN_ACCESS_WRITEONLY;
988
989#if 0
990 //SvL: Not true; verified in NT! (also messed up access of files on
991 // readonly volumes)
992 // CreateFile with OPEN_ALWAYS & GENERIC_READ on non-existing file
993 // -> creates 0 size file, WriteFile is not allowed
994 // Same in OS/2.
995 /* if creating a file, access cannot be readonly! */
996 if (openFlag & OPEN_ACTION_CREATE_IF_NEW &&
997 (!(openMode & OPEN_ACCESS_READWRITE) &&
998 !(openMode & OPEN_ACCESS_WRITEONLY))) {
999 openMode |= OPEN_ACCESS_READWRITE;
1000 }
1001#endif
1002
1003 if(strlen(lpszFile) == 2 && lpszFile[1] == ':') {
1004 //app tries to open physical disk
1005 openMode |= OPEN_FLAGS_DASD;
1006 }
1007 int retry = 0;
1008 while (retry < 3)
1009 {
1010 dprintf(("DosOpen %s openFlag=%x openMode=%x", lpszFile, openFlag, openMode));
1011 rc = DosOpen((PSZ)lpszFile,
1012 &hFile,
1013 &actionTaken,
1014 fileSize,
1015 fileAttr,
1016 openFlag,
1017 openMode,
1018 NULL);
1019 if (rc == ERROR_TOO_MANY_OPEN_FILES)
1020 {
1021 ULONG CurMaxFH;
1022 LONG ReqCount = 32;
1023
1024 rc = DosSetRelMaxFH(&ReqCount, &CurMaxFH);
1025 if(rc) {
1026 dprintf(("DosSetRelMaxFH returned %d", rc));
1027 SetLastError(ERROR_TOO_MANY_OPEN_FILES_W);
1028 return INVALID_HANDLE_VALUE_W;
1029 }
1030 dprintf(("DosOpen failed -> increased nr open files to %d", CurMaxFH));
1031 }
1032 #if 0
1033 else if (rc == ERROR_ACCESS_DENIED && (openFlag & OPEN_ACTION_REPLACE_IF_EXISTS))
1034 { /* kso: I have great problems with the REPLACE not working
1035 * So, I guess this emulation may help...
1036 * This problem exist on WS4eB SMP FP1 and Warp4 FP14/Kernel 14059 at least.
1037 */
1038 rc = DosOpen((PSZ)lpszFile,
1039 &hFile,
1040 &actionTaken,
1041 fileSize,
1042 fileAttr,
1043 (openFlag & ~OPEN_ACTION_REPLACE_IF_EXISTS) | OPEN_ACTION_OPEN_IF_EXISTS,
1044 openMode,
1045 NULL);
1046 if (rc == NO_ERROR)
1047 {
1048 rc = DosSetFileSize(hFile, 0);
1049 if (!rc && fileSize > 0)
1050 rc = DosSetFileSize(hFile, fileSize);
1051 if (rc)
1052 {
1053 DosClose(hFile);
1054 hFile = NULLHANDLE;
1055
1056 if (rc != ERROR_TOO_MANY_OPEN_FILES)
1057 break;
1058 }
1059 else break;
1060 }
1061 }
1062 #endif
1063 else break;
1064 retry++;
1065 }
1066
1067 if(rc)
1068 {
1069 // @@@AH 2001-06-02 Win2k SP2 returns error 2 in this case
1070 int winError = error2WinError(rc);
1071 if (winError == ERROR_OPEN_FAILED_W)
1072 winError = ERROR_FILE_NOT_FOUND_W;
1073 SetLastError(winError);
1074 return INVALID_HANDLE_VALUE_W;
1075 }
1076 SetLastError(ERROR_SUCCESS_W);
1077 return hFile;
1078}
1079//******************************************************************************
1080//******************************************************************************
1081DWORD OSLibDosOpenFile(CHAR *lpszFile, UINT fuMode)
1082{
1083 ULONG actionTaken = 0;
1084 ULONG fileSize = 0;
1085 ULONG fileAttr = FILE_NORMAL;
1086 ULONG openFlag = 0;
1087 ULONG openMode = 0;
1088 APIRET rc = ERROR_NOT_ENOUGH_MEMORY;
1089 HFILE hFile;
1090
1091 if(!(fuMode & (OF_CREATE_W | OF_READWRITE_W | OF_WRITE_W)))
1092 {
1093 openMode |= OPEN_ACCESS_READONLY;
1094 openFlag |= OPEN_ACTION_OPEN_IF_EXISTS;
1095 }
1096 else
1097 {
1098 if(fuMode & OF_CREATE_W) {
1099 openFlag |= OPEN_ACTION_CREATE_IF_NEW |
1100 OPEN_ACTION_REPLACE_IF_EXISTS;
1101 }
1102 else openFlag |= OPEN_ACTION_OPEN_IF_EXISTS;
1103
1104 if(fuMode & OF_READWRITE_W)
1105 openMode |= OPEN_ACCESS_READWRITE;
1106 else
1107 if(fuMode & OF_WRITE_W)
1108 openMode |= OPEN_ACCESS_WRITEONLY;
1109 else
1110 if(fuMode & OF_CREATE_W)
1111 openMode |= OPEN_ACCESS_READWRITE;
1112 }
1113
1114 if((fuMode & OF_SHARE_DENY_WRITE_W) ||
1115 !(fuMode & (OF_SHARE_DENY_READ_W | OF_SHARE_DENY_NONE_W | OF_SHARE_EXCLUSIVE_W)))
1116 openMode |= OPEN_SHARE_DENYWRITE;
1117 else
1118 if (fuMode & OF_SHARE_DENY_NONE_W)
1119 openMode |= OPEN_SHARE_DENYNONE;
1120 else
1121 if (fuMode & OF_SHARE_DENY_READ_W)
1122 openMode |= OPEN_SHARE_DENYREAD;
1123 else
1124 if (fuMode & OF_SHARE_EXCLUSIVE_W)
1125 openMode |= OPEN_SHARE_DENYREADWRITE;
1126
1127 rc = DosOpen((PSZ)lpszFile,
1128 &hFile,
1129 &actionTaken,
1130 fileSize,
1131 fileAttr,
1132 openFlag,
1133 openMode,
1134 NULL);
1135
1136 if(rc != NO_ERROR)
1137 {
1138 if(fuMode & OF_EXIST_W)
1139 {
1140 if(rc == ERROR_OPEN_FAILED || rc == ERROR_FILE_NOT_FOUND)
1141 {
1142 SetLastError(ERROR_FILE_NOT_FOUND_W);
1143 return HFILE_ERROR_W;
1144 }
1145 }
1146 if((rc == ERROR_OPEN_FAILED) && (openFlag & OPEN_ACTION_OPEN_IF_EXISTS))
1147 {
1148 SetLastError(ERROR_FILE_NOT_FOUND_W);
1149 }
1150 else SetLastError(error2WinError(rc));
1151
1152 return HFILE_ERROR_W;
1153 }
1154 SetLastError(ERROR_SUCCESS_W);
1155 return hFile;
1156}
1157//******************************************************************************
1158//******************************************************************************
1159BOOL OSLibDosLockFile(DWORD hFile, DWORD dwFlags,
1160 DWORD OffsetLow, DWORD OffsetHigh,
1161 DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh,
1162 LPOVERLAPPED lpOverlapped)
1163{
1164 APIRET rc;
1165
1166 // Set 5 secs timeout for locking file and no other can access this
1167 // file region
1168
1169 if(lpOverlapped) {//TODO:
1170 dprintf(("OSLibDosLockFile: overlapped lock not yet implemented!!"));
1171 }
1172 //TODO: Locking region crossing end of file is permitted. Works in OS/2??
1173 if(f64BitIO)
1174 {
1175 FILELOCKL lockRangeL;
1176
1177 lockRangeL.lOffset.ulLo = OffsetLow;
1178 lockRangeL.lOffset.ulHi = OffsetHigh;
1179 lockRangeL.lRange.ulLo = nNumberOfBytesToLockLow;
1180 lockRangeL.lRange.ulHi = nNumberOfBytesToLockHigh;
1181
1182 rc = OdinDosSetFileLocksL(hFile, NULL, &lockRangeL,
1183 (dwFlags & LOCKFILE_FAIL_IMMEDIATELY_W) ? 0 : 5000, 0);
1184 //SvL: 64 bits values are only supported by JFS
1185 // Try the 32 bits DosSetFileLocks if it fails
1186 // (TODO: should check the partition type instead)
1187 if(rc == ERROR_INVALID_PARAMETER && (OffsetHigh || nNumberOfBytesToLockHigh)) {
1188 goto oldlock;
1189 }
1190 }
1191 else
1192 {
1193oldlock:
1194 FILELOCK lockRange = { OffsetLow, nNumberOfBytesToLockLow };
1195
1196 rc = DosSetFileLocks(hFile, NULL, &lockRange,
1197 (dwFlags & LOCKFILE_FAIL_IMMEDIATELY_W) ? 0 : 5000, 0);
1198 }
1199 if(rc) {
1200 SetLastError(error2WinError(rc));
1201 return FALSE;
1202 }
1203 SetLastError(ERROR_SUCCESS_W);
1204 return TRUE;
1205}
1206//******************************************************************************
1207//******************************************************************************
1208BOOL OSLibDosUnlockFile(DWORD hFile, DWORD OffsetLow, DWORD OffsetHigh,
1209 DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh,
1210 LPOVERLAPPED lpOverlapped)
1211{
1212 APIRET rc;
1213
1214 // Set 5 secs timeout for unlocking file and no other can access this
1215 // file region
1216
1217 if(lpOverlapped) {//TODO:
1218 dprintf(("OSLibDosUnlockFile: overlapped unlock not yet implemented!!"));
1219 }
1220 if(f64BitIO)
1221 {
1222 FILELOCKL unlockRangeL;
1223
1224 unlockRangeL.lOffset.ulLo = OffsetLow;
1225 unlockRangeL.lOffset.ulHi = OffsetHigh;
1226 unlockRangeL.lRange.ulLo = nNumberOfBytesToLockLow;
1227 unlockRangeL.lRange.ulHi = nNumberOfBytesToLockHigh;
1228
1229 rc = OdinDosSetFileLocksL(hFile, &unlockRangeL, NULL, 5000, 0);
1230 //SvL: 64 bits values are only supported by JFS
1231 // Try the 32 bits DosSetFileLocks if it fails
1232 // (TODO: should check the partition type instead)
1233 if(rc == ERROR_INVALID_PARAMETER && (OffsetHigh || nNumberOfBytesToLockHigh)) {
1234 goto oldlock;
1235 }
1236 }
1237 else
1238 {
1239oldlock:
1240 FILELOCK unlockRange = { OffsetLow, nNumberOfBytesToLockLow };
1241
1242 rc = DosSetFileLocks(hFile, &unlockRange, NULL, 5000, 0);
1243 }
1244 if(rc) {
1245 SetLastError(error2WinError(rc));
1246 return FALSE;
1247 }
1248 SetLastError(ERROR_SUCCESS_W);
1249 return TRUE;
1250}
1251//******************************************************************************
1252//******************************************************************************
1253BOOL OSLibDosFlushFileBuffers(DWORD hFile)
1254{
1255 APIRET rc;
1256
1257 rc = DosResetBuffer(hFile);
1258 SetLastError(error2WinError(rc));
1259 return (rc == NO_ERROR);
1260}
1261//******************************************************************************
1262//******************************************************************************
1263DWORD OSLibDosGetFileSize(DWORD hFile, LPDWORD lpdwFileSizeHigh)
1264{
1265 APIRET rc;
1266 ULONG sizeLow;
1267
1268 if(f64BitIO)
1269 {
1270 FILESTATUS3L fsts3ConfigInfoL = {{0}};
1271 ULONG ulBufSize = sizeof(FILESTATUS3L);
1272
1273 rc = DosQueryFileInfo(hFile, FIL_STANDARDL, &fsts3ConfigInfoL, ulBufSize);
1274 if(lpdwFileSizeHigh) {
1275 *lpdwFileSizeHigh = fsts3ConfigInfoL.cbFile.ulHi;
1276 }
1277 sizeLow = fsts3ConfigInfoL.cbFile.ulLo;
1278 }
1279 else
1280 {
1281 FILESTATUS3 fsts3ConfigInfo = {{0}};
1282 ULONG ulBufSize = sizeof(FILESTATUS3);
1283
1284 if(lpdwFileSizeHigh) {
1285 *lpdwFileSizeHigh = 0;
1286 }
1287 rc = DosQueryFileInfo(hFile, FIL_STANDARD, &fsts3ConfigInfo, ulBufSize);
1288 sizeLow = fsts3ConfigInfo.cbFile;
1289 }
1290 if(rc) {
1291 SetLastError(error2WinError(rc));
1292 return -1;
1293 }
1294 SetLastError(ERROR_SUCCESS_W);
1295 return sizeLow;
1296}
1297//******************************************************************************
1298//******************************************************************************
1299DWORD OSLibDosSetFilePointer(DWORD hFile, DWORD OffsetLow, DWORD *OffsetHigh, DWORD method)
1300{
1301 LONGLONG offsetL;
1302 LONGLONG newoffsetL;
1303 APIRET rc;
1304 DWORD newoffset;
1305
1306 switch(method)
1307 {
1308 case FILE_BEGIN_W:
1309 method = FILE_BEGIN;
1310 break;
1311
1312 case FILE_CURRENT_W:
1313 method = FILE_CURRENT;
1314 break;
1315
1316 case FILE_END_W:
1317 method = FILE_END;
1318 break;
1319 }
1320
1321 // PH Note: for a negative 32-bit seek, the OS/2 64-bit version
1322 // needs to be skipped.
1323 if( (f64BitIO) && (OffsetHigh) )
1324 {
1325 offsetL.ulLo = OffsetLow;
1326 offsetL.ulHi = (OffsetHigh) ? *OffsetHigh : 0;
1327 rc = OdinDosSetFilePtrL(hFile, offsetL, method, &newoffsetL);
1328 if(OffsetHigh) {
1329 *OffsetHigh = newoffsetL.ulHi;
1330 }
1331 newoffset = newoffsetL.ulLo;
1332 }
1333 else rc = DosSetFilePtr(hFile, OffsetLow, method, &newoffset);
1334
1335 if(rc)
1336 {
1337 SetLastError(error2WinError(rc));
1338 return -1;
1339 }
1340 SetLastError(ERROR_SUCCESS_W);
1341 return newoffset;
1342}
1343//******************************************************************************
1344//******************************************************************************
1345BOOL OSLibDosSetEndOfFile(DWORD hFile)
1346{
1347 ULONG newFilePos;
1348 LONGLONG FilePosL = {0,0};
1349 LONGLONG newFilePosL;
1350 APIRET rc;
1351
1352 if(f64BitIO) {
1353 rc = OdinDosSetFilePtrL(hFile, FilePosL, FILE_CURRENT, &newFilePosL);
1354 if(rc == 0) {
1355 rc = OdinDosSetFileSizeL(hFile, newFilePosL);
1356 }
1357 }
1358 else {
1359 rc = DosSetFilePtr(hFile, 0, FILE_CURRENT, &newFilePos);
1360 if(rc == 0) {
1361 rc = DosSetFileSize(hFile, newFilePos);
1362 }
1363 }
1364 if(rc) {
1365 SetLastError(error2WinError(rc));
1366 return FALSE;
1367 }
1368 SetLastError(ERROR_SUCCESS_W);
1369 return TRUE;
1370}
1371//******************************************************************************
1372//******************************************************************************
1373BOOL OSLibDosGetFileInformationByHandle(DWORD hFile, BY_HANDLE_FILE_INFORMATION* pInfo)
1374{
1375 APIRET rc;
1376
1377 if(f64BitIO)
1378 {
1379 FILESTATUS4L statusL = { 0 };
1380
1381 rc = DosQueryFileInfo(hFile, FIL_QUERYEASIZEL,
1382 &statusL, sizeof(statusL));
1383 if(rc == NO_ERROR)
1384 {
1385 pInfo->dwFileAttributes = 0;
1386 if(!(statusL.attrFile & NOT_NORMAL))
1387 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_NORMAL_W;
1388 if(statusL.attrFile & FILE_READONLY)
1389 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_READONLY_W;
1390 if(statusL.attrFile & FILE_HIDDEN)
1391 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN_W;
1392 if(statusL.attrFile & FILE_SYSTEM)
1393 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_SYSTEM_W;
1394 if(statusL.attrFile & FILE_DIRECTORY)
1395 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY_W;
1396 if(statusL.attrFile & FILE_ARCHIVED)
1397 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_ARCHIVE_W;
1398
1399 pmDateTimeToFileTime(&statusL.fdateCreation,
1400 &statusL.ftimeCreation,
1401 &pInfo->ftCreationTime);
1402 pmDateTimeToFileTime(&statusL.fdateLastAccess,
1403 &statusL.ftimeLastAccess,
1404 &pInfo->ftLastAccessTime);
1405 pmDateTimeToFileTime(&statusL.fdateLastWrite,
1406 &statusL.ftimeLastWrite,
1407 &pInfo->ftLastWriteTime);
1408
1409 pInfo->nFileSizeHigh = statusL.cbFile.ulHi;
1410 pInfo->nFileSizeLow = statusL.cbFile.ulLo;
1411 pInfo->dwVolumeSerialNumber = 0; //todo
1412 pInfo->nNumberOfLinks = 1;
1413 pInfo->nFileIndexHigh = 0;
1414 pInfo->nFileIndexLow = 0;
1415 }
1416 }
1417 else
1418 {
1419 FILESTATUS4 status = { 0 };
1420
1421 rc = DosQueryFileInfo(hFile, FIL_QUERYEASIZE, &status,
1422 sizeof(status));
1423 if(rc == NO_ERROR)
1424 {
1425 pInfo->dwFileAttributes = 0;
1426 if(!(status.attrFile & NOT_NORMAL))
1427 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_NORMAL_W;
1428 if(status.attrFile & FILE_READONLY)
1429 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_READONLY_W;
1430 if(status.attrFile & FILE_HIDDEN)
1431 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN_W;
1432 if(status.attrFile & FILE_SYSTEM)
1433 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_SYSTEM_W;
1434 if(status.attrFile & FILE_DIRECTORY)
1435 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY_W;
1436 if(status.attrFile & FILE_ARCHIVED)
1437 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_ARCHIVE_W;
1438
1439 pmDateTimeToFileTime(&status.fdateCreation,
1440 &status.ftimeCreation,
1441 &pInfo->ftCreationTime);
1442 pmDateTimeToFileTime(&status.fdateLastAccess,
1443 &status.ftimeLastAccess,
1444 &pInfo->ftLastAccessTime);
1445 pmDateTimeToFileTime(&status.fdateLastWrite,
1446 &status.ftimeLastWrite,
1447 &pInfo->ftLastWriteTime);
1448
1449 pInfo->nFileSizeHigh = 0;
1450 pInfo->nFileSizeLow = status.cbFile;
1451 pInfo->dwVolumeSerialNumber = 0; //todo
1452 pInfo->nNumberOfLinks = 1;
1453 pInfo->nFileIndexHigh = 0;
1454 pInfo->nFileIndexLow = 0;
1455 }
1456 }
1457 if(rc) {
1458 SetLastError(error2WinError(rc));
1459 return FALSE;
1460 }
1461 SetLastError(ERROR_SUCCESS_W);
1462 return TRUE;
1463}
1464//******************************************************************************
1465//******************************************************************************
1466BOOL OSLibDosSetFileTime(DWORD hFile, WORD creationdate, WORD creationtime,
1467 WORD lastaccessdate, WORD lastaccesstime,
1468 WORD lastwritedate, WORD lastwritetime)
1469{
1470 FILESTATUS3 fileInfo;
1471 APIRET rc;
1472
1473 rc = DosQueryFileInfo(hFile, FIL_STANDARD, &fileInfo, sizeof(fileInfo));
1474
1475 if(rc == NO_ERROR)
1476 {
1477 if(creationdate && creationtime) {
1478 fileInfo.fdateCreation = *(FDATE *)&creationdate;
1479 fileInfo.ftimeCreation = *(FTIME *)&creationtime;
1480 }
1481 if(lastaccessdate && lastaccesstime) {
1482 fileInfo.fdateLastAccess = *(FDATE *)&lastaccessdate;
1483 fileInfo.ftimeLastAccess = *(FTIME *)&lastaccesstime;
1484 }
1485 if(lastwritedate && lastwritetime) {
1486 fileInfo.fdateLastWrite = *(FDATE *)&lastwritedate;
1487 fileInfo.ftimeLastWrite = *(FTIME *)&lastwritetime;
1488 }
1489
1490 rc = DosSetFileInfo(hFile, FIL_STANDARD, &fileInfo, sizeof(fileInfo));
1491 }
1492
1493 if(rc)
1494 {
1495 SetLastError(error2WinError(rc));
1496 return FALSE;
1497 }
1498 SetLastError(ERROR_SUCCESS_W);
1499 return TRUE;
1500}
1501//******************************************************************************
1502//******************************************************************************
1503BOOL OSLibDosGetFileTime(DWORD hFile, WORD *creationdate, WORD *creationtime,
1504 WORD *lastaccessdate, WORD *lastaccesstime,
1505 WORD *lastwritedate, WORD *lastwritetime)
1506{
1507 FILESTATUS3 fileInfo;
1508 APIRET rc;
1509
1510 rc = DosQueryFileInfo(hFile, FIL_STANDARD, &fileInfo, sizeof(fileInfo));
1511
1512 if(rc == NO_ERROR)
1513 {
1514 *creationdate = *(WORD *)&fileInfo.fdateCreation;
1515 *creationtime = *(WORD *)&fileInfo.ftimeCreation;
1516 *lastaccessdate = *(WORD *)&fileInfo.fdateLastAccess;
1517 *lastaccesstime = *(WORD *)&fileInfo.ftimeLastAccess;
1518 *lastwritedate = *(WORD *)&fileInfo.fdateLastWrite;
1519 *lastwritetime = *(WORD *)&fileInfo.ftimeLastWrite;
1520 }
1521
1522 if(rc)
1523 {
1524 SetLastError(error2WinError(rc));
1525 return FALSE;
1526 }
1527 SetLastError(ERROR_SUCCESS_W);
1528 return TRUE;
1529}
1530//******************************************************************************
1531//******************************************************************************
1532DWORD OSLibDosSetFilePtr2(DWORD hFile, DWORD offset, DWORD method)
1533{
1534 DWORD newoffset;
1535 APIRET rc;
1536
1537
1538 rc = DosSetFilePtr(hFile, offset, method, &newoffset);
1539 if(rc) {
1540 dprintf(("DosSetFilePtr Error rc:%d", rc));
1541 return -1;
1542 }
1543 else return newoffset;
1544}
1545//******************************************************************************
1546//******************************************************************************
1547DWORD OSLibDosDupHandle(DWORD hFile, DWORD *hNew)
1548{
1549 *hNew = -1;
1550 return DosDupHandle(hFile, hNew);
1551}
1552//******************************************************************************
1553//Returns time spent in kernel & user mode in milliseconds
1554//******************************************************************************
1555BOOL OSLibDosQueryProcTimes(DWORD procid, ULONG *kerneltime, ULONG *usertime)
1556{
1557 APIRET rc;
1558 char *buf;
1559 ULONG size;
1560 ULONG nrthreads = 4;
1561
1562tryagain:
1563 size = sizeof(QTOPLEVEL)+sizeof(QGLOBAL)+sizeof(QPROCESS) + nrthreads*sizeof(QTHREAD);
1564 buf = (char *)malloc(size);
1565 rc = DosQuerySysState(0x1, RESERVED, procid, RESERVED, (PCHAR)buf, size);
1566
1567 if(rc) {
1568 free(buf);
1569 if(rc == ERROR_BUFFER_OVERFLOW) {
1570 nrthreads += 4;
1571 goto tryagain;
1572 }
1573 return FALSE;
1574 }
1575 PQTOPLEVEL top = (PQTOPLEVEL)buf;
1576
1577 *kerneltime = 0;
1578 *usertime = 0;
1579 for(int i=0;i<top->procdata->threadcnt;i++) {
1580 *kerneltime += top->procdata->threads[i].systime;
1581 *usertime += top->procdata->threads[i].usertime;
1582 }
1583 free(buf);
1584 return TRUE;
1585}
1586//******************************************************************************
1587//******************************************************************************
1588// TODO: implement SecurityAttributes parameter
1589DWORD OSLibDosCreateNamedPipe(LPCTSTR lpName,
1590 DWORD dwOpenMode,
1591 DWORD dwPipeMode,
1592 DWORD nMaxInstances,
1593 DWORD nOutBufferSize,
1594 DWORD nInBufferSize,
1595 DWORD nDefaultTimeOut,
1596 LPSECURITY_ATTRIBUTES lpSecurityAttributes)
1597{ DWORD dwOS2Mode = 0;
1598 DWORD dwOS2PipeMode = 0;
1599 LPSTR lpOS2Name;
1600 DWORD hPipe;
1601 DWORD rc, ulAction;
1602
1603 if (dwOpenMode & PIPE_ACCESS_DUPLEX_W)
1604 dwOS2Mode |= NP_ACCESS_DUPLEX;
1605 else
1606 if (dwOpenMode & PIPE_ACCESS_INBOUND_W)
1607 dwOS2Mode |= NP_ACCESS_INBOUND;
1608 else
1609 if (dwOpenMode & PIPE_ACCESS_OUTBOUND_W)
1610 dwOS2Mode |= NP_ACCESS_OUTBOUND;
1611 // TODO:
1612 // if(dwOpenMode & FILE_FLAG_OVERLAPPED)
1613 // if(dwOpenMode & WRITE_DAC)
1614 // if(dwOpenMode & WRITE_OWNER)
1615 // if(dwOpenMode & ACCESS_SYSTEM_SECURITY)
1616 if(dwOpenMode & FILE_FLAG_WRITE_THROUGH_W)
1617 dwOS2Mode |= NP_WRITEBEHIND; // FIXME: I'm not sure!
1618
1619 if (dwPipeMode & PIPE_WAIT_W)
1620 dwOS2PipeMode |= NP_WAIT;
1621 if (dwPipeMode & PIPE_NOWAIT_W)
1622 dwOS2PipeMode |= NP_NOWAIT;
1623 if (dwPipeMode & PIPE_READMODE_BYTE_W)
1624 dwOS2PipeMode |= NP_READMODE_BYTE;
1625 if (dwPipeMode & PIPE_READMODE_MESSAGE_W)
1626 dwOS2PipeMode |= NP_READMODE_MESSAGE;
1627 if (dwPipeMode & PIPE_TYPE_BYTE_W)
1628 dwOS2PipeMode |= NP_TYPE_BYTE;
1629 if (dwPipeMode & PIPE_TYPE_MESSAGE_W)
1630 dwOS2PipeMode |= NP_TYPE_MESSAGE;
1631
1632 if (nMaxInstances>0xff)
1633 {
1634 SetLastError(ERROR_INVALID_PARAMETER_W); // ERROR_INVALID_PARAMETER
1635 return -1; // INVALID_HANDLE_VALUE
1636 }
1637 dwOS2PipeMode |= nMaxInstances;
1638
1639 if (strstr(lpName,"\\\\."))
1640 {
1641 // If pipe is created on the local machine
1642 // we must delete string \\. because
1643 // in Windows named pipes scheme is a \\.\PIPE\pipename
1644 // but in OS/2 only \PIPE\pipename
1645 lpOS2Name = (LPSTR)lpName + 3;
1646 }
1647 else lpOS2Name = (LPSTR)lpName;
1648
1649 dprintf(("DosCreateNPipe(%s,%x,%x,%x,%x,%x)",lpOS2Name,dwOS2Mode,dwOS2PipeMode,nInBufferSize,nOutBufferSize,nDefaultTimeOut));
1650
1651 //if the windows app tries to open another instance of an existing pipe, then
1652 //we must use DosOpen here. So first try DosOpen, if that fails then we can
1653 //create the named pipe
1654 rc = DosOpen(lpOS2Name, &hPipe, &ulAction, 0, FILE_NORMAL, FILE_OPEN,
1655 ((dwOpenMode & PIPE_ACCESS_INBOUND_W) ? OPEN_ACCESS_READWRITE : OPEN_ACCESS_READONLY) |
1656 OPEN_SHARE_DENYNONE, NULL);
1657
1658 if(rc == NO_ERROR) {
1659 dprintf(("Opening of existing named pipe succeeded"));
1660 return hPipe;
1661 }
1662
1663 rc=DosCreateNPipe(lpOS2Name,
1664 &hPipe,
1665 dwOS2Mode,
1666 dwOS2PipeMode,
1667 nInBufferSize,
1668 nInBufferSize,
1669 nDefaultTimeOut); // Timeouts must be tested!
1670
1671 dprintf(("DosCreateNPipe rc=%d",rc));
1672 if (rc)
1673 {
1674 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER_W));
1675 return -1; // INVALID_HANDLE_VALUE
1676 }
1677 return hPipe;
1678}
1679//******************************************************************************
1680//******************************************************************************
1681BOOL OSLibSetNamedPipeState(DWORD hNamedPipe, DWORD dwPipeMode)
1682{
1683 ULONG dwOS2PipeMode = 0;
1684 APIRET rc;
1685
1686 if (dwPipeMode & PIPE_WAIT_W)
1687 dwOS2PipeMode |= NP_WAIT;
1688 if (dwPipeMode & PIPE_NOWAIT_W)
1689 dwOS2PipeMode |= NP_NOWAIT;
1690 if (dwPipeMode & PIPE_READMODE_BYTE_W)
1691 dwOS2PipeMode |= NP_READMODE_BYTE;
1692 if (dwPipeMode & PIPE_READMODE_MESSAGE_W)
1693 dwOS2PipeMode |= NP_READMODE_MESSAGE;
1694
1695 rc = DosSetNPHState(hNamedPipe, dwOS2PipeMode);
1696 if(rc) {
1697 SetLastError(error2WinError(rc, ERROR_INVALID_PARAMETER_W));
1698 return FALSE;
1699 }
1700 return TRUE;
1701}
1702//******************************************************************************
1703//******************************************************************************
1704DWORD OSLibDosOpenPipe(LPCTSTR lpName,
1705 DWORD fuAccess,
1706 DWORD fuShare,
1707 LPSECURITY_ATTRIBUTES lpSecurityAttributes,
1708 DWORD fuCreate,
1709 DWORD fuAttrFlags)
1710{
1711 LPSTR lpOS2Name;
1712 ULONG hPipe;
1713 ULONG rc, ulAction;
1714 ULONG openFlag = 0;
1715 ULONG openMode = 0;
1716
1717
1718 switch(fuCreate)
1719 {
1720 case CREATE_NEW_W:
1721 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_FAIL_IF_EXISTS;
1722 break;
1723 case CREATE_ALWAYS_W:
1724 /* kso 2000-11-26: Not sure if OPEN_ACTION_REPLACE_IF_EXISTS is correct here! It is correct according to
1725 * MSDN, but not according to "The Win32 API SuperBible". Anyway I haven't got time to check it out in
1726 * NT now.
1727 * The problem is that OPEN_ACTION_REPLACE_IF_EXISTS requires write access. It failes with
1728 * rc = ERROR_ACCESS_DENIED (5). Quick fix, use OPEN_IF_EXIST if readonly access.
1729 */
1730 if (fuAccess & GENERIC_WRITE_W)
1731 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS;
1732 else
1733 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
1734 break;
1735 case OPEN_EXISTING_W:
1736 openFlag |= OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
1737 break;
1738 case OPEN_ALWAYS_W:
1739 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
1740 break;
1741 case TRUNCATE_EXISTING_W:
1742 openFlag |= OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS;
1743 break;
1744 }
1745
1746 if(fuAttrFlags & FILE_FLAG_WRITE_THROUGH_W) openMode |= OPEN_FLAGS_WRITE_THROUGH;
1747 if(fuAttrFlags & FILE_FLAG_NO_BUFFERING_W) openMode |= OPEN_FLAGS_NO_CACHE;
1748 if(fuAttrFlags & FILE_FLAG_RANDOM_ACCESS_W) openMode |= OPEN_FLAGS_RANDOM;
1749 if(fuAttrFlags & FILE_FLAG_SEQUENTIAL_SCAN_W) openMode |= OPEN_FLAGS_SEQUENTIAL;
1750 // TODO: FILE_FLAG_BACKUP_SEMANTICS_W
1751 // FILE_FLAG_POSIX_SEMANTICS_W are not supported
1752
1753 //TODO: FILE_SHARE_DELETE
1754 if((fuShare & (FILE_SHARE_READ_W | FILE_SHARE_WRITE_W)) == 0 )
1755 openMode |= OPEN_SHARE_DENYREADWRITE;
1756 else
1757 if((fuShare & (FILE_SHARE_READ_W | FILE_SHARE_WRITE_W)) == (FILE_SHARE_READ_W | FILE_SHARE_WRITE_W))
1758 openMode |= OPEN_SHARE_DENYNONE;
1759 else
1760 if(fuShare & FILE_SHARE_READ_W)
1761 openMode |= OPEN_SHARE_DENYWRITE;
1762 else
1763 if(fuShare & FILE_SHARE_WRITE_W)
1764 openMode |= OPEN_SHARE_DENYREAD;
1765
1766 if(fuAccess == (GENERIC_READ_W | GENERIC_WRITE_W))
1767 openMode |= OPEN_ACCESS_READWRITE;
1768 else
1769 if(fuAccess & GENERIC_READ_W)
1770 openMode |= OPEN_ACCESS_READONLY;
1771 else
1772 if(fuAccess & GENERIC_WRITE_W)
1773 openMode |= OPEN_ACCESS_WRITEONLY;
1774
1775 if (strstr(lpName,"\\\\."))
1776 {
1777 // If pipe is created on the local machine
1778 // we must delete string \\. because
1779 // in Windows named pipes scheme is a \\.\PIPE\pipename
1780 // but in OS/2 only \PIPE\pipename
1781 lpOS2Name = (LPSTR)lpName + 3;
1782 }
1783 else lpOS2Name = (LPSTR)lpName;
1784
1785 rc = DosOpen(lpOS2Name, &hPipe, &ulAction, 0, 0,
1786 openFlag, openMode, NULL);
1787
1788 if(rc == NO_ERROR) {
1789 dprintf(("Opening of existing named pipe succeeded"));
1790 return hPipe;
1791 }
1792
1793 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER_W));
1794 return -1; // INVALID_HANDLE_VALUE
1795}
1796
1797//******************************************************************************
1798//******************************************************************************
1799// TODO: implement lpOverlapped parameter!
1800BOOL OSLibDosConnectNamedPipe(DWORD hNamedPipe, LPOVERLAPPED lpOverlapped)
1801{
1802 DWORD rc;
1803
1804 rc=DosConnectNPipe(hNamedPipe);
1805 dprintf(("DosConnectNPipe rc=%d",rc));
1806
1807 if (!rc) return (TRUE);
1808 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1809
1810 return (FALSE);
1811}
1812
1813//******************************************************************************
1814//******************************************************************************
1815BOOL OSLibDosCallNamedPipe( LPCTSTR lpNamedPipeName,
1816 LPVOID lpInBuffer,
1817 DWORD nInBufferSize,
1818 LPVOID lpOutBuffer,
1819 DWORD nOutBufferSize,
1820 LPDWORD lpBytesRead,
1821 DWORD nTimeOut )
1822{
1823 LPSTR lpOS2Name;
1824 DWORD rc;
1825
1826 if (strstr(lpNamedPipeName,"\\\\."))
1827 {
1828 // If pipe is created on the local machine
1829 // we must delete string \\. because
1830 // in Windows named pipes scheme is a \\.\PIPE\pipename
1831 // but in OS/2 only \PIPE\pipename
1832 lpOS2Name = (LPSTR)lpNamedPipeName + 3;
1833 }
1834 else lpOS2Name = (LPSTR)lpNamedPipeName;
1835
1836 rc=DosCallNPipe(lpOS2Name,
1837 lpInBuffer,
1838 nInBufferSize,
1839 lpOutBuffer,
1840 nOutBufferSize,
1841 lpBytesRead,
1842 nTimeOut );
1843
1844
1845 if (!rc) return (TRUE);
1846 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1847
1848 return (FALSE);
1849}
1850
1851//******************************************************************************
1852//******************************************************************************
1853BOOL OSLibDosTransactNamedPipe( DWORD hNamedPipe,
1854 LPVOID lpInBuffer,
1855 DWORD nInBufferSize,
1856 LPVOID lpOutBuffer,
1857 DWORD nOutBufferSize,
1858 LPDWORD lpBytesRead,
1859 LPOVERLAPPED lpOverlapped)
1860{
1861 DWORD rc;
1862
1863 rc=DosTransactNPipe(hNamedPipe,
1864 lpOutBuffer,
1865 nOutBufferSize,
1866 lpInBuffer,
1867 nInBufferSize,
1868 lpBytesRead);
1869
1870 dprintf(("DosTransactNPipe returned rc=%d");)
1871 if (!rc) return (TRUE);
1872 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1873
1874 return (FALSE);
1875}
1876
1877//******************************************************************************
1878//******************************************************************************
1879BOOL OSLibDosPeekNamedPipe(DWORD hPipe,
1880 LPVOID lpvBuffer,
1881 DWORD cbBuffer,
1882 LPDWORD lpcbRead,
1883 LPDWORD lpcbAvail,
1884 LPDWORD lpcbMessage)
1885{
1886 DWORD rc;
1887 AVAILDATA availData ={0};
1888 ULONG ulDummy;
1889
1890 rc=DosPeekNPipe(hPipe,lpvBuffer,cbBuffer,lpcbRead,&availData,&ulDummy);
1891
1892 dprintf(("DosPeekNPipe returned rc=%d",rc));
1893
1894 if (!rc)
1895 {
1896 *lpcbAvail = availData.cbpipe;
1897 *lpcbMessage = availData.cbmessage;
1898 return (TRUE);
1899 }
1900 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1901
1902 return (FALSE);
1903}
1904//******************************************************************************
1905//******************************************************************************
1906BOOL OSLibDosDisconnectNamedPipe(DWORD hPipe)
1907{
1908 DWORD rc;
1909
1910 rc=DosDisConnectNPipe(hPipe);
1911
1912 dprintf(("DosDisConnectNPipe returned rc=%d",rc));
1913
1914 if (!rc) return TRUE;
1915 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1916
1917 return (FALSE);
1918}
1919//******************************************************************************
1920//******************************************************************************
1921BOOL OSLibDosWaitNamedPipe(LPCSTR lpszNamedPipeName,
1922 DWORD dwTimeout)
1923{
1924 LPSTR lpOS2Name;
1925 DWORD rc;
1926
1927 if (strstr(lpszNamedPipeName,"\\\\."))
1928 {
1929 // If pipe is created on the local machine
1930 // we must delete string \\. because
1931 // in Windows named pipes scheme is a \\.\PIPE\pipename
1932 // but in OS/2 only \PIPE\pipename
1933 lpOS2Name = (LPSTR)lpszNamedPipeName + 3;
1934 }
1935 else lpOS2Name = (LPSTR)lpszNamedPipeName;
1936
1937 rc=DosWaitNPipe(lpOS2Name,dwTimeout);
1938
1939 dprintf(("DosWaitNPipe returned rc=%d",rc));
1940
1941 if (!rc) return TRUE;
1942 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1943
1944 return (FALSE);
1945}
1946//******************************************************************************
1947//******************************************************************************
1948BOOL isRoot(CHAR* name)
1949{
1950 if (name[1] == ':')
1951 {
1952 //local name (x:\)
1953 return (name[2] == 0) || !strchr(&name[3],'\\');
1954 } else if (name[0] == '\\')
1955 {
1956 //UNC name (\\resource\drive\)
1957 CHAR *drive,*dir;
1958
1959 drive = strchr(&name[2],'\\');
1960 if (!drive) return FALSE;
1961 dir = strchr(&drive[1],'\\');
1962 if (!dir) return TRUE;
1963 return !strchr(&dir[1],'\\');
1964 } else return FALSE; //unknown
1965}
1966//******************************************************************************
1967//******************************************************************************
1968inline CHAR system2DOSCharacter(CHAR ch)
1969{
1970 switch(ch)
1971 {
1972 case ' ':
1973 case '.':
1974 case '~':
1975 return '_';
1976
1977 default:
1978 return toupper(ch);
1979 }
1980}
1981
1982// TODO: not finished nor correct!!!!
1983VOID long2ShortName(CHAR* longName, CHAR* shortName)
1984{
1985 // check for uplink / root: "." and ".."
1986 if (longName[0] == '.')
1987 {
1988 // if ((strcmp(longName,".") == 0) || (strcmp(longName,"..") == 0))
1989 if (longName[1] == 0) // "."
1990 {
1991 shortName[0] = '.';
1992 shortName[1] = 0;
1993 return;
1994 }
1995
1996 if (longName[1] == '.' && longName[2] == 0) // ".."
1997 {
1998 shortName[0] = '.';
1999 shortName[1] = '.';
2000 shortName[2] = 0;
2001 return;
2002 }
2003 }
2004 else
2005 // check for empty name
2006 if(longName[0] == 0)
2007 {
2008 shortName[0] = 0;
2009 return;
2010 }
2011
2012 INT x;
2013 CHAR *source = longName;
2014
2015 // Test if longName is 8:3 compliant and simply copy
2016 // the filename.
2017 BOOL flag83 = TRUE;
2018
2019 // verify forbidden characters
2020 for (x = 0;
2021 (x < 8) &&
2022 (flag83 == TRUE);
2023 x++)
2024 {
2025 switch (*source)
2026 {
2027 case '.': // a period will cause the loop to abort!
2028 x=1000;
2029 break;
2030
2031 case '/': case '?':
2032 case '*': case ':':
2033 case '\\': case '"':
2034 case ' ':
2035 flag83 = FALSE;
2036 break;
2037 default:
2038 source++;
2039 break;
2040 }
2041 }
2042
2043 // verify we're on a period now
2044 if (flag83 == TRUE)
2045 if (*source != '.')
2046 flag83 = FALSE;
2047 else source++;
2048
2049 // verify extension
2050 if (flag83 == TRUE)
2051 for (INT y = 0;
2052 (y < 3) && (flag83 == TRUE);
2053 y++)
2054 {
2055 switch (*source)
2056 {
2057 case '/': case '?':
2058 case '*': case ':':
2059 case '\\': case '"':
2060 case ' ': case '.':
2061 flag83 = FALSE;
2062 break;
2063 }
2064 source++;
2065 }
2066
2067 // verify we're at the end of the string now
2068 if (flag83 == TRUE)
2069 if (*source != 0)
2070 flag83 = FALSE;
2071
2072 // OK, done
2073 if (flag83 == TRUE)
2074 {
2075 // we might not alter any character here, since
2076 // an app opening a specific file with an 8:3 "alias",
2077 // would surely fail.
2078 strcpy(shortName, longName);
2079
2080 return; // Done
2081 }
2082
2083
2084 // @@@PH
2085 shortName[0] = 0; // this function is disabled anyway ...
2086 return;
2087
2088 CHAR *dest = shortName;
2089 CHAR *ext = strrchr(longName,'.');
2090
2091 //CB: quick and dirty, real FILE~12.EXT is too slow
2092 //PH: We'd have to count the number of non-8:3-compliant files
2093 // within a directory. Or simpler: the number of files within
2094 // the current directory.
2095
2096 //8 character file name
2097 for (x = 0;x < 8;x++)
2098 {
2099 if ((source == ext) || (source[0] == 0)) break;
2100 dest[0] = system2DOSCharacter(source[0]);
2101 source++;
2102 dest++;
2103 }
2104
2105 if (source[0] == 0)
2106 {
2107 dest[0] = 0;
2108 return;
2109 }
2110
2111 if (source != ext)
2112 {
2113 //longName > 8 characters, insert ~1
2114 shortName[6] = '~';
2115 shortName[7] = '1';
2116 }
2117
2118 if (ext)
2119 {
2120 //add extension, 3 characters
2121 dest[0] = ext[0];
2122 dest++;
2123 ext++;
2124 for (x = 0;x < 3;x++)
2125 {
2126 if (ext[0] == 0) break;
2127 dest[0] = system2DOSCharacter(ext[0]);
2128 ext++;
2129 dest++;
2130 }
2131 }
2132 dest[0] = 0;
2133}
2134//******************************************************************************
2135//******************************************************************************
2136VOID translateFileResults(FILESTATUS3 *pResult,LPWIN32_FIND_DATAA pFind,CHAR* achName)
2137{
2138 CHAR* name;
2139
2140 pFind->dwReserved0 = pFind->dwReserved1 = 0;
2141 pFind->dwFileAttributes = pm2WinFileAttributes(pResult->attrFile);
2142
2143 pmDateTimeToFileTime(&pResult->fdateCreation,&pResult->ftimeCreation,&pFind->ftCreationTime);
2144 pmDateTimeToFileTime(&pResult->fdateLastAccess,&pResult->ftimeLastAccess,&pFind->ftLastAccessTime);
2145 pmDateTimeToFileTime(&pResult->fdateLastWrite,&pResult->ftimeLastWrite,&pFind->ftLastWriteTime);
2146
2147 pFind->nFileSizeHigh = 0; //CB: fixme
2148 pFind->nFileSizeLow = pResult->cbFile;
2149 name = strrchr(achName,'\\');
2150 if (name)
2151 {
2152 name++;
2153 strcpy(pFind->cFileName,name);
2154 }
2155 else
2156 pFind->cFileName[0] = 0;
2157
2158 long2ShortName(pFind->cFileName,pFind->cAlternateFileName);
2159}
2160
2161VOID translateFindResults(FILEFINDBUF3 *pResult,LPWIN32_FIND_DATAA pFind)
2162{
2163 pFind->dwFileAttributes = pm2WinFileAttributes(pResult->attrFile);
2164 pFind->dwReserved0 = pFind->dwReserved1 = 0;
2165
2166 pmDateTimeToFileTime(&pResult->fdateCreation,&pResult->ftimeCreation,&pFind->ftCreationTime);
2167 pmDateTimeToFileTime(&pResult->fdateLastAccess,&pResult->ftimeLastAccess,&pFind->ftLastAccessTime);
2168 pmDateTimeToFileTime(&pResult->fdateLastWrite,&pResult->ftimeLastWrite,&pFind->ftLastWriteTime);
2169
2170 pFind->nFileSizeHigh = 0; //CB: fixme
2171 pFind->nFileSizeLow = pResult->cbFile;
2172 strcpy(pFind->cFileName,pResult->achName);
2173 long2ShortName(pFind->cFileName,pFind->cAlternateFileName);
2174}
2175//******************************************************************************
2176//******************************************************************************
2177DWORD OSLibDosFindFirst(LPCSTR lpFileName,WIN32_FIND_DATAA* lpFindFileData)
2178{
2179 HDIR hDir = -1;
2180 ULONG attrs;
2181 FILEFINDBUF3 result;
2182 ULONG searchCount = 1;
2183
2184 attrs = FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY | FILE_ARCHIVED;
2185 result.achName[0] = 0;
2186
2187 ULONG oldmode = SetErrorMode(SEM_FAILCRITICALERRORS_W);
2188 APIRET rc = DosFindFirst((PSZ)lpFileName,&hDir,attrs,&result,sizeof(result),&searchCount,FIL_STANDARD);
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 searchCount = 1;
2199 APIRET rc = DosFindNext(hDir,&result,sizeof(result),&searchCount);
2200 if (rc)
2201 {
2202 DosFindClose(hDir);
2203 SetLastError(error2WinError(rc));
2204
2205 SetErrorMode(oldmode);
2206 return INVALID_HANDLE_VALUE_W;
2207 }
2208 }
2209 }
2210
2211 // enable i/o kernel exceptions again
2212 SetErrorMode(oldmode);
2213
2214 if(rc)
2215 {
2216 DosFindClose(hDir);
2217 SetLastError(error2WinError(rc));
2218 return INVALID_HANDLE_VALUE_W;
2219 }
2220 translateFindResults(&result,lpFindFileData);
2221 SetLastError(ERROR_SUCCESS_W);
2222 return hDir;
2223}
2224//******************************************************************************
2225// NOTE: returns "." and ".." in root
2226//******************************************************************************
2227DWORD OSLibDosFindFirstMulti(LPCSTR lpFileName,WIN32_FIND_DATAA *lpFindFileData,DWORD *count)
2228{
2229 HDIR hDir = -1;
2230 ULONG attrs;
2231 FILEFINDBUF3 *result,*data;
2232 ULONG searchCount = *count;
2233
2234 attrs = FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY | FILE_ARCHIVED;
2235 result = (FILEFINDBUF3*)malloc(searchCount*sizeof(FILEFINDBUF3));
2236
2237 ULONG oldmode = SetErrorMode(SEM_FAILCRITICALERRORS_W);
2238 APIRET rc = DosFindFirst((PSZ)lpFileName,&hDir,attrs,result,searchCount*sizeof(FILEFINDBUF3),&searchCount,FIL_STANDARD);
2239 SetErrorMode(oldmode);
2240 if (rc)
2241 {
2242 free(result);
2243 *count = 0;
2244 SetLastError(error2WinError(rc));
2245
2246 return INVALID_HANDLE_VALUE_W;
2247 }
2248
2249 data = result;
2250 for (int x = 0;x < searchCount;x++)
2251 {
2252 translateFindResults(data,&lpFindFileData[x]);
2253 data = (FILEFINDBUF3*)(((DWORD)data)+data->oNextEntryOffset);
2254 }
2255 free(result);
2256 *count = searchCount;
2257
2258 SetLastError(ERROR_SUCCESS_W);
2259 return hDir;
2260}
2261//******************************************************************************
2262//******************************************************************************
2263BOOL OSLibDosFindNext(DWORD hFindFile,WIN32_FIND_DATAA *lpFindFileData)
2264{
2265 FILEFINDBUF3 result;
2266 ULONG searchCount = 1;
2267
2268 APIRET rc = DosFindNext((HDIR)hFindFile,&result,sizeof(result),&searchCount);
2269 if (rc)
2270 {
2271 SetLastError(error2WinError(rc));
2272
2273 return FALSE;
2274 }
2275
2276 translateFindResults(&result,lpFindFileData);
2277 SetLastError(ERROR_SUCCESS_W);
2278 return TRUE;
2279}
2280//******************************************************************************
2281//******************************************************************************
2282BOOL OSLibDosFindNextMulti(DWORD hFindFile,WIN32_FIND_DATAA *lpFindFileData,DWORD *count)
2283{
2284 FILEFINDBUF3 *result,*data;
2285 ULONG searchCount = *count;
2286
2287 result = (FILEFINDBUF3*)malloc(searchCount*sizeof(FILEFINDBUF3));
2288 APIRET rc = DosFindNext((HDIR)hFindFile,result,searchCount*sizeof(FILEFINDBUF3),&searchCount);
2289 if (rc)
2290 {
2291 free(result);
2292 *count = 0;
2293 SetLastError(error2WinError(rc));
2294
2295 return FALSE;
2296 }
2297
2298 data = result;
2299 for (int x = 0;x < searchCount;x++)
2300 {
2301 translateFindResults(data,&lpFindFileData[x]);
2302 data = (FILEFINDBUF3*)(((DWORD)data)+data->oNextEntryOffset);
2303 }
2304 free(result);
2305 *count = searchCount;
2306
2307 SetLastError(ERROR_SUCCESS_W);
2308 return TRUE;
2309}
2310//******************************************************************************
2311//******************************************************************************
2312BOOL OSLibDosFindClose(DWORD hFindFile)
2313{
2314 APIRET rc = DosFindClose((HDIR)hFindFile);
2315 if (rc)
2316 {
2317 SetLastError(error2WinError(rc));
2318 return FALSE;
2319 }
2320
2321 SetLastError(ERROR_SUCCESS_W);
2322 return TRUE;
2323}
2324//******************************************************************************
2325#define FSATTACH_SIZE 256
2326//******************************************************************************
2327DWORD OSLibDosQueryVolumeFS(int drive, LPSTR lpFileSystemNameBuffer, DWORD nFileSystemNameSize)
2328{
2329 PFSQBUFFER2 fsinfo = (PFSQBUFFER2) alloca(FSATTACH_SIZE);
2330 ULONG cb = FSATTACH_SIZE;
2331 char drv[3] = "A:";
2332 char *fsname;
2333 APIRET rc;
2334
2335 if(lpFileSystemNameBuffer == NULL) {
2336 DebugInt3();
2337 return ERROR_INVALID_PARAMETER_W;
2338 }
2339 drv[0] = (char)('A' + drive - 1);
2340
2341 ULONG oldmode = SetErrorMode(SEM_FAILCRITICALERRORS_W);
2342 rc = DosQueryFSAttach(drv, 1, FSAIL_QUERYNAME, fsinfo, &cb);
2343 SetErrorMode(oldmode);
2344
2345 switch(rc) {
2346 case ERROR_INVALID_DRIVE:
2347 return ERROR_INVALID_DRIVE_W;
2348 case ERROR_NO_VOLUME_LABEL:
2349 return ERROR_NO_VOLUME_LABEL_W;
2350 case NO_ERROR:
2351 break;
2352 default:
2353 return ERROR_NOT_ENOUGH_MEMORY; //whatever
2354 }
2355
2356 fsname = (char *)&fsinfo->szName[0] + fsinfo->cbName + 1;
2357
2358 /* @@@PH 2000/08/10 CMD.EXE querys with nFileSystemNameSize == 0
2359 * however does NOT expect to receive an error.
2360 */
2361 strncpy(lpFileSystemNameBuffer,
2362 fsname,
2363 nFileSystemNameSize);
2364 /*
2365 if(strlen(fsname) < nFileSystemNameSize) {
2366 strcpy(lpFileSystemNameBuffer, fsname);
2367 }
2368 else return ERROR_BUFFER_OVERFLOW_W;
2369 */
2370 return 0;
2371}
2372//******************************************************************************
2373typedef struct _FSINFOBUF
2374{
2375 ULONG ulVolser; /* Volume serial number */
2376 VOLUMELABEL vol; /* Volume lable */
2377} FSINFOBUF;
2378//******************************************************************************
2379DWORD OSLibDosQueryVolumeSerialAndName(int drive, LPDWORD lpVolumeSerialNumber,
2380 LPSTR lpVolumeNameBuffer, DWORD nVolumeNameSize)
2381{
2382 FSINFOBUF fsi;
2383 APIRET rc;
2384
2385 ULONG oldmode = SetErrorMode(SEM_FAILCRITICALERRORS_W);
2386 rc = DosQueryFSInfo(drive, FSIL_VOLSER, &fsi, sizeof(fsi));
2387 SetErrorMode(oldmode);
2388
2389 switch(rc) {
2390 case ERROR_INVALID_DRIVE:
2391 return ERROR_INVALID_DRIVE_W;
2392 case ERROR_NO_VOLUME_LABEL:
2393 return ERROR_NO_VOLUME_LABEL_W;
2394 case NO_ERROR:
2395 break;
2396 default:
2397 return ERROR_NOT_ENOUGH_MEMORY; //whatever
2398 }
2399
2400 if(lpVolumeSerialNumber) {
2401 *lpVolumeSerialNumber = fsi.ulVolser;
2402 }
2403 if(lpVolumeNameBuffer)
2404 {
2405 if(nVolumeNameSize > fsi.vol.cch) {
2406 strcpy(lpVolumeNameBuffer, (PCHAR)fsi.vol.szVolLabel);
2407 }
2408 else return ERROR_BUFFER_OVERFLOW_W;
2409 }
2410
2411 return ERROR_SUCCESS_W;
2412}
2413//******************************************************************************
2414//******************************************************************************
2415BOOL OSLibGetDiskFreeSpace(LPSTR lpRootPathName, LPDWORD lpSectorsPerCluster,
2416 LPDWORD lpBytesPerSector, LPDWORD lpNumberOfFreeClusters,
2417 LPDWORD lpTotalNumberOfClusters)
2418{
2419 ULONG diskNum;
2420 FSALLOCATE fsAlloc;
2421 APIRET rc;
2422
2423 if(lpRootPathName == 0)
2424 diskNum = 0;
2425 else
2426 if('A' <= *lpRootPathName && *lpRootPathName <= 'Z' )
2427 diskNum = *lpRootPathName - 'A' + 1;
2428 else
2429 if('a' <= *lpRootPathName && *lpRootPathName <= 'z' )
2430 diskNum = *lpRootPathName - 'a' + 1;
2431 else
2432 diskNum = 0;
2433
2434 ULONG oldmode = SetErrorMode(SEM_FAILCRITICALERRORS_W);
2435 rc = DosQueryFSInfo(diskNum, FSIL_ALLOC, &fsAlloc, sizeof(fsAlloc));
2436 SetErrorMode(oldmode);
2437
2438 if(rc == 0)
2439 {
2440 *lpSectorsPerCluster = fsAlloc.cSectorUnit;
2441 *lpBytesPerSector = fsAlloc.cbSector;
2442 *lpNumberOfFreeClusters = fsAlloc.cUnitAvail;
2443 *lpTotalNumberOfClusters = fsAlloc.cUnit;
2444 SetLastError(ERROR_SUCCESS_W);
2445 return TRUE;
2446 }
2447 SetLastError(error2WinError(rc));
2448 return FALSE;
2449}
2450//******************************************************************************
2451//******************************************************************************
2452BOOL OSLibDosGetDiskGeometry(HANDLE hDisk, DWORD cDisk, PVOID pdiskgeom)
2453{
2454 PDISK_GEOMETRY pGeom = (PDISK_GEOMETRY)pdiskgeom;
2455 BYTE param[2] = {0, 0};
2456 ULONG parsize = 2;
2457 BIOSPARAMETERBLOCK bpb;
2458 ULONG datasize = sizeof(bpb);
2459 APIRET rc;
2460
2461 dprintf(("OSLibDosGetDiskGeometry %x %d %x", hDisk, cDisk, pdiskgeom));
2462 param[1] = cDisk - 'A';
2463 rc = DosDevIOCtl((hDisk) ? hDisk : -1, IOCTL_DISK, DSK_GETDEVICEPARAMS, param, 2, &parsize, &bpb, sizeof(bpb), &datasize);
2464 if(rc == 0)
2465 {
2466 pGeom->SectorsPerTrack = bpb.usSectorsPerTrack;
2467 pGeom->BytesPerSector = bpb.usBytesPerSector;
2468 pGeom->TracksPerCylinder = 80; //TODO:!!!!!
2469 pGeom->Cylinders.u.LowPart = bpb.cCylinders;
2470 pGeom->Cylinders.u.HighPart = 0;
2471 switch(bpb.bDeviceType) {
2472 case DEVTYPE_48TPI:
2473 pGeom->MediaType = F5_360_512; //?????
2474 break;
2475 case DEVTYPE_96TPI:
2476 pGeom->MediaType = F5_1Pt2_512; //?????
2477 break;
2478 case DEVTYPE_35:
2479 pGeom->MediaType = F3_720_512;
2480 break;
2481 case DEVTYPE_8SD:
2482 case DEVTYPE_8DD:
2483 pGeom->MediaType = RemovableMedia;
2484 break;
2485 case DEVTYPE_FIXED:
2486 pGeom->MediaType = FixedMedia;
2487 break;
2488 case DEVTYPE_TAPE:
2489 pGeom->MediaType = RemovableMedia;
2490 break;
2491 case DEVTYPE_UNKNOWN: //others, include 1.44 3.5 inch disk drive
2492 pGeom->MediaType = F3_1Pt44_512;
2493 break;
2494 case 8: //RW optical disk
2495 pGeom->MediaType = RemovableMedia;
2496 break;
2497 case 9: //2.88 3.5 inch disk
2498 pGeom->MediaType = F3_2Pt88_512;
2499 break;
2500 }
2501 SetLastError(ERROR_SUCCESS_W);
2502 return TRUE;
2503 }
2504 dprintf(("OSLibDosGetDiskGeometry: error %d -> %d", rc, error2WinError(rc)));
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 PVOID pTiledParm = pParm;
2580 BOOL flagTiledParm = FALSE;
2581 PVOID pTiledData = pData;
2582 BOOL flagTiledData = FALSE;
2583
2584#define MEM_TILED_CEILING 0x1fffffff
2585
2586 // bounce buffer support
2587 // make sure no parameter or data buffer can pass the tiled memory region
2588 // barrier (usually 512MB). OS/2 kernel does not correctly translate these
2589 // addresses to a 16:16 address used in device driver land. In fact,
2590 // DosDevIOCtl is not a high memory enabled API!
2591
2592 if (pTiledParm && (((DWORD)pTiledParm + max(dwParmMaxLen, *pdwParmLen)) > MEM_TILED_CEILING))
2593 {
2594 rc = DosAllocMem(&pTiledParm, dwParmMaxLen, PAG_READ | PAG_WRITE);
2595 if (rc)
2596 goto _exit_ioctl;
2597
2598 flagTiledParm = TRUE;
2599 }
2600
2601 if (pTiledData && (((DWORD)pTiledData + max(dwDataMaxLen, *pdwDataLen)) > MEM_TILED_CEILING))
2602 {
2603 rc = DosAllocMem(&pTiledData, dwDataMaxLen, PAG_READ | PAG_WRITE);
2604 if (rc)
2605 goto _exit_ioctl;
2606
2607 flagTiledData = TRUE;
2608 }
2609
2610 // copy data from real buffers to
2611 // bounce buffers if necessary
2612 if (pTiledParm != pParm)
2613 memcpy(pTiledParm, pParm, *pdwParmLen);
2614
2615 if (pTiledData != pData)
2616 memcpy(pTiledData, pData, *pdwDataLen);
2617
2618
2619 rc = DosDevIOCtl( (HFILE)hFile, dwCat, dwFunc,
2620 pParm, dwParmMaxLen, pdwParmLen,
2621 pData, dwDataMaxLen, pdwDataLen);
2622
2623 // copy data from bounce buffers to real
2624 // target buffers if necessary
2625 if (pTiledParm != pParm)
2626 memcpy(pParm, pTiledParm, *pdwParmLen);
2627
2628 if (pTiledData != pData)
2629 memcpy(pData, pTiledData, *pdwDataLen);
2630
2631
2632 _exit_ioctl:
2633
2634 // deallocate bounce buffers
2635 if (flagTiledParm)
2636 DosFreeMem(pTiledParm);
2637
2638 if (flagTiledData)
2639 DosFreeMem(pTiledData);
2640
2641 SetLastError(error2WinError(rc, ERROR_INVALID_HANDLE));
2642 return (DWORD)rc;
2643}
2644
2645/**
2646 * Pure wrapper for DosQueryModulName which returns the OS/2 returncode.
2647 * @returns Returncode from DosQueryModuleName.
2648 * @param hModule Handle of the module which name we query.
2649 * @param cchName Length of the output name buffer.
2650 * @param pszname Pointer to the output name buffer.
2651 * @status Completely implemented.
2652 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
2653 */
2654ULONG OSLibDosQueryModuleName(ULONG hModule, int cchName, char *pszName)
2655{
2656 return DosQueryModuleName(hModule, cchName, pszName);
2657}
2658
2659
2660HINSTANCE OSLibDosLoadModule(LPSTR szModName)
2661{
2662 APIRET rc;
2663 HMODULE hModule = NULLHANDLE;
2664 char name[ CCHMAXPATH ];
2665
2666 rc = DosLoadModule(name, CCHMAXPATH, szModName, &hModule);
2667 if(rc) {
2668 SetLastError(error2WinError(rc,ERROR_FILE_NOT_FOUND));
2669 return 0;
2670 }
2671 SetLastError(ERROR_SUCCESS_W);
2672 return hModule;
2673}
2674//******************************************************************************
2675//******************************************************************************
2676void OSLibDosFreeModule(HINSTANCE hinst)
2677{
2678 DosFreeModule(hinst);
2679}
2680//******************************************************************************
2681//******************************************************************************
2682ULONG OSLibDosQuerySysInfo(ULONG iStart, ULONG iLast, PVOID pBuf, ULONG cbBuf)
2683{
2684 APIRET rc;
2685
2686 rc = DosQuerySysInfo(iStart, iLast, pBuf, cbBuf);
2687 SetLastError(error2WinError(rc,ERROR_INVALID_HANDLE));
2688 return rc;
2689}
2690//******************************************************************************
2691//returned length is number of characters required or used for current dir
2692//*excluding* terminator
2693//******************************************************************************
2694ULONG OSLibDosQueryDir(DWORD length, LPSTR lpszCurDir)
2695{
2696 ULONG drivemap, currentdisk, len;
2697 char *lpszCurDriveAndDir = lpszCurDir +3;
2698 APIRET rc;
2699
2700 len = (length > 3) ? length - 3 : 0;
2701
2702 rc = DosQueryCurrentDir(0, lpszCurDriveAndDir, &len);
2703 if(rc != ERROR_BUFFER_OVERFLOW)
2704 {
2705 if(rc)
2706 {
2707 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER));
2708 return 0;
2709 }
2710 len = strlen(lpszCurDriveAndDir) + 3;
2711
2712 // Dir returned by DosQueryCurDir doesn't include drive, so add it
2713 DosQueryCurrentDisk(&currentdisk, &drivemap);
2714
2715 if(isupper(lpszCurDir[3])) {
2716 lpszCurDir[0] = (char)('A' - 1 + currentdisk);
2717 }
2718 else lpszCurDir[0] = (char)('a' - 1 + currentdisk);
2719
2720 lpszCurDir[1] = ':';
2721 lpszCurDir[2] = '\\';
2722 }
2723 else len += 3; // + 3 since DosQueryCurDir doesn't include drive
2724
2725 SetLastError(ERROR_SUCCESS_W);
2726 return len;
2727}
2728//******************************************************************************
2729//******************************************************************************
2730BOOL OSLibDosBeep(DWORD ulFreq, DWORD ulDuration)
2731{
2732 APIRET rc;
2733
2734 if (ulDuration == -1)
2735 {
2736 SetLastError(ERROR_NOT_SUPPORTED_W);
2737 return FALSE;
2738 }
2739 rc = DosBeep(ulFreq, ulDuration);
2740 SetLastError(error2WinError(rc,ERROR_INVALID_HANDLE));
2741
2742 return (rc == 0);
2743}
2744//******************************************************************************
2745//******************************************************************************
2746ULONG OSLibDosGetModuleFileName(HMODULE hModule, LPTSTR lpszPath, DWORD cchPath)
2747{
2748 PTIB pTIB;
2749 PPIB pPIB;
2750 APIRET rc;
2751
2752 if(hModule == -1 || hModule == 0)
2753 {
2754 DosGetInfoBlocks(&pTIB, &pPIB);
2755 hModule = pPIB->pib_hmte;
2756 }
2757 *lpszPath = 0;
2758 rc = DosQueryModuleName(hModule, cchPath, lpszPath);
2759
2760 DWORD len = strlen(lpszPath);
2761 SetLastError(error2WinError(rc,ERROR_INVALID_HANDLE));
2762 return len;
2763}
2764//******************************************************************************
2765//******************************************************************************
2766ULONG OSLibDosGetProcAddress(HMODULE hModule, LPCSTR lpszProc)
2767{
2768 APIRET rc;
2769 PFN pfn = NULL;
2770 ULONG ordinal = (((ULONG)lpszProc) <= 0xFFFF) ? (ULONG)lpszProc : 0;
2771 HMODULE hmod = (HMODULE)hModule;
2772
2773 rc = DosQueryProcAddr( hmod, ordinal, (PSZ)lpszProc, &pfn );
2774 if(rc == ERROR_INVALID_HANDLE && pfn == NULL) {
2775 CHAR pszError[32], pszModule[CCHMAXPATH];
2776
2777 if(DosQueryModuleName( hmod, CCHMAXPATH, pszModule ) == 0 &&
2778 DosLoadModule( pszError, 32, pszModule, &hmod ) == 0)
2779 {
2780 rc = DosQueryProcAddr(hmod, ordinal, (PSZ)lpszProc, &pfn);
2781 }
2782 }
2783 SetLastError(error2WinError(rc,ERROR_INVALID_HANDLE));
2784
2785 return (ULONG)pfn;
2786}
2787//******************************************************************************
2788//******************************************************************************
Note: See TracBrowser for help on using the repository browser.