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

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

DF: fixes for translating ascii strings between os/2 & windows (in case of different code pages)

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