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

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

.

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