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

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

Fixes in HandleManager and Device Handlers

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