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

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

Implemented Get/SetProcessAffinityMask & SetThreadAffinityMask

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