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

Last change on this file since 8259 was 8259, checked in by bird, 23 years ago

Optimized and rearranged OSLibGetDriveType. (Removed used of static IOCtl data, etc.).

File size: 102.5 KB
Line 
1/* $Id: oslibdos.cpp,v 1.97 2002-04-13 06:31:53 bird 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#if 0
1731 //TODO:
1732 if(dwOpenMode & FILE_FLAG_FIRST_PIPE_INSTANCE_W) {
1733 DosClose(hPipe);
1734 SetLastError(ERROR_ALREADY_EXISTS_W);
1735 return -1;
1736 }
1737 else {
1738#endif
1739 dprintf(("Opening of existing named pipe succeeded"));
1740 SetLastError(ERROR_SUCCESS_W);
1741 return hPipe;
1742// }
1743 }
1744
1745 rc=DosCreateNPipe(lpOS2Name,
1746 &hPipe,
1747 dwOS2Mode,
1748 dwOS2PipeMode,
1749 nInBufferSize,
1750 nInBufferSize,
1751 nDefaultTimeOut); // Timeouts must be tested!
1752
1753 dprintf(("DosCreateNPipe rc=%d",rc));
1754 if (rc)
1755 {
1756 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER_W));
1757 return -1; // INVALID_HANDLE_VALUE
1758 }
1759 SetLastError(ERROR_SUCCESS_W);
1760 return hPipe;
1761}
1762//******************************************************************************
1763//******************************************************************************
1764BOOL OSLibSetNamedPipeState(DWORD hNamedPipe, DWORD dwPipeMode)
1765{
1766 ULONG dwOS2PipeMode = 0;
1767 APIRET rc;
1768
1769 if (dwPipeMode & PIPE_WAIT_W)
1770 dwOS2PipeMode |= NP_WAIT;
1771 if (dwPipeMode & PIPE_NOWAIT_W)
1772 dwOS2PipeMode |= NP_NOWAIT;
1773 if (dwPipeMode & PIPE_READMODE_BYTE_W)
1774 dwOS2PipeMode |= NP_READMODE_BYTE;
1775 if (dwPipeMode & PIPE_READMODE_MESSAGE_W)
1776 dwOS2PipeMode |= NP_READMODE_MESSAGE;
1777
1778 rc = DosSetNPHState(hNamedPipe, dwOS2PipeMode);
1779 if(rc) {
1780 SetLastError(error2WinError(rc, ERROR_INVALID_PARAMETER_W));
1781 return FALSE;
1782 }
1783 SetLastError(ERROR_SUCCESS_W);
1784 return TRUE;
1785}
1786//******************************************************************************
1787//******************************************************************************
1788DWORD OSLibDosOpenPipe(LPCTSTR lpName,
1789 DWORD fuAccess,
1790 DWORD fuShare,
1791 LPSECURITY_ATTRIBUTES lpSecurityAttributes,
1792 DWORD fuCreate,
1793 DWORD fuAttrFlags)
1794{
1795 LPSTR lpOS2Name;
1796 ULONG hPipe;
1797 ULONG rc, ulAction;
1798 ULONG openFlag = 0;
1799 ULONG openMode = 0;
1800
1801
1802 switch(fuCreate)
1803 {
1804 case CREATE_NEW_W:
1805 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_FAIL_IF_EXISTS;
1806 break;
1807 case CREATE_ALWAYS_W:
1808 /* kso 2000-11-26: Not sure if OPEN_ACTION_REPLACE_IF_EXISTS is correct here! It is correct according to
1809 * MSDN, but not according to "The Win32 API SuperBible". Anyway I haven't got time to check it out in
1810 * NT now.
1811 * The problem is that OPEN_ACTION_REPLACE_IF_EXISTS requires write access. It failes with
1812 * rc = ERROR_ACCESS_DENIED (5). Quick fix, use OPEN_IF_EXIST if readonly access.
1813 */
1814 if (fuAccess & GENERIC_WRITE_W)
1815 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS;
1816 else
1817 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
1818 break;
1819 case OPEN_EXISTING_W:
1820 openFlag |= OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
1821 break;
1822 case OPEN_ALWAYS_W:
1823 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
1824 break;
1825 case TRUNCATE_EXISTING_W:
1826 openFlag |= OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS;
1827 break;
1828 }
1829
1830 if(fuAttrFlags & FILE_FLAG_WRITE_THROUGH_W) openMode |= OPEN_FLAGS_WRITE_THROUGH;
1831 if(fuAttrFlags & FILE_FLAG_NO_BUFFERING_W) openMode |= OPEN_FLAGS_NO_CACHE;
1832 if(fuAttrFlags & FILE_FLAG_RANDOM_ACCESS_W) openMode |= OPEN_FLAGS_RANDOM;
1833 if(fuAttrFlags & FILE_FLAG_SEQUENTIAL_SCAN_W) openMode |= OPEN_FLAGS_SEQUENTIAL;
1834 // TODO: FILE_FLAG_BACKUP_SEMANTICS_W
1835 // FILE_FLAG_POSIX_SEMANTICS_W are not supported
1836
1837 //TODO: FILE_SHARE_DELETE
1838 if((fuShare & (FILE_SHARE_READ_W | FILE_SHARE_WRITE_W)) == 0 )
1839 openMode |= OPEN_SHARE_DENYREADWRITE;
1840 else
1841 if((fuShare & (FILE_SHARE_READ_W | FILE_SHARE_WRITE_W)) == (FILE_SHARE_READ_W | FILE_SHARE_WRITE_W))
1842 openMode |= OPEN_SHARE_DENYNONE;
1843 else
1844 if(fuShare & FILE_SHARE_READ_W)
1845 openMode |= OPEN_SHARE_DENYWRITE;
1846 else
1847 if(fuShare & FILE_SHARE_WRITE_W)
1848 openMode |= OPEN_SHARE_DENYREAD;
1849
1850 if(fuAccess == (GENERIC_READ_W | GENERIC_WRITE_W))
1851 openMode |= OPEN_ACCESS_READWRITE;
1852 else
1853 if(fuAccess & GENERIC_READ_W)
1854 openMode |= OPEN_ACCESS_READONLY;
1855 else
1856 if(fuAccess & GENERIC_WRITE_W)
1857 openMode |= OPEN_ACCESS_WRITEONLY;
1858
1859 if (strstr(lpName,"\\\\."))
1860 {
1861 // If pipe is created on the local machine
1862 // we must delete string \\. because
1863 // in Windows named pipes scheme is a \\.\PIPE\pipename
1864 // but in OS/2 only \PIPE\pipename
1865 lpOS2Name = (LPSTR)lpName + 3;
1866 }
1867 else lpOS2Name = (LPSTR)lpName;
1868
1869 rc = DosOpen(lpOS2Name, &hPipe, &ulAction, 0, 0,
1870 openFlag, openMode, NULL);
1871
1872 if(rc == NO_ERROR) {
1873 dprintf(("Opening of existing named pipe succeeded"));
1874 SetLastError(ERROR_SUCCESS_W);
1875 return hPipe;
1876 }
1877
1878 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER_W));
1879 return -1; // INVALID_HANDLE_VALUE
1880}
1881
1882//******************************************************************************
1883//******************************************************************************
1884// TODO: implement lpOverlapped parameter!
1885BOOL OSLibDosConnectNamedPipe(DWORD hNamedPipe, LPOVERLAPPED lpOverlapped)
1886{
1887 DWORD rc;
1888
1889 rc=DosConnectNPipe(hNamedPipe);
1890 dprintf(("DosConnectNPipe rc=%d",rc));
1891
1892 if(rc == NO_ERROR) {
1893 SetLastError(ERROR_SUCCESS_W);
1894 return (TRUE);
1895 }
1896 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1897 return (FALSE);
1898}
1899
1900//******************************************************************************
1901//******************************************************************************
1902BOOL OSLibDosCallNamedPipe( LPCTSTR lpNamedPipeName,
1903 LPVOID lpInBuffer,
1904 DWORD nInBufferSize,
1905 LPVOID lpOutBuffer,
1906 DWORD nOutBufferSize,
1907 LPDWORD lpBytesRead,
1908 DWORD nTimeOut )
1909{
1910 LPSTR lpOS2Name;
1911 DWORD rc;
1912
1913 if (strstr(lpNamedPipeName,"\\\\."))
1914 {
1915 // If pipe is created on the local machine
1916 // we must delete string \\. because
1917 // in Windows named pipes scheme is a \\.\PIPE\pipename
1918 // but in OS/2 only \PIPE\pipename
1919 lpOS2Name = (LPSTR)lpNamedPipeName + 3;
1920 }
1921 else lpOS2Name = (LPSTR)lpNamedPipeName;
1922
1923 rc=DosCallNPipe(lpOS2Name,
1924 lpInBuffer,
1925 nInBufferSize,
1926 lpOutBuffer,
1927 nOutBufferSize,
1928 lpBytesRead,
1929 nTimeOut );
1930
1931
1932 if(rc == NO_ERROR) {
1933 SetLastError(ERROR_SUCCESS_W);
1934 return (TRUE);
1935 }
1936 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1937 return (FALSE);
1938}
1939
1940//******************************************************************************
1941//******************************************************************************
1942BOOL OSLibDosTransactNamedPipe( DWORD hNamedPipe,
1943 LPVOID lpInBuffer,
1944 DWORD nInBufferSize,
1945 LPVOID lpOutBuffer,
1946 DWORD nOutBufferSize,
1947 LPDWORD lpBytesRead,
1948 LPOVERLAPPED lpOverlapped)
1949{
1950 DWORD rc;
1951
1952 rc=DosTransactNPipe(hNamedPipe,
1953 lpOutBuffer,
1954 nOutBufferSize,
1955 lpInBuffer,
1956 nInBufferSize,
1957 lpBytesRead);
1958
1959 dprintf(("DosTransactNPipe returned rc=%d");)
1960 if(rc == NO_ERROR) {
1961 SetLastError(ERROR_SUCCESS_W);
1962 return (TRUE);
1963 }
1964 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1965 return (FALSE);
1966}
1967
1968//******************************************************************************
1969//******************************************************************************
1970BOOL OSLibDosPeekNamedPipe(DWORD hPipe,
1971 LPVOID lpvBuffer,
1972 DWORD cbBuffer,
1973 LPDWORD lpcbRead,
1974 LPDWORD lpcbAvail,
1975 LPDWORD lpcbMessage)
1976{
1977 DWORD rc;
1978 AVAILDATA availData ={0};
1979 ULONG ulDummy;
1980
1981 rc=DosPeekNPipe(hPipe,lpvBuffer,cbBuffer,lpcbRead,&availData,&ulDummy);
1982
1983 dprintf(("DosPeekNPipe returned rc=%d",rc));
1984
1985 if (!rc)
1986 {
1987 *lpcbAvail = availData.cbpipe;
1988 *lpcbMessage = availData.cbmessage;
1989 SetLastError(ERROR_SUCCESS_W);
1990 return (TRUE);
1991 }
1992 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1993 return (FALSE);
1994}
1995//******************************************************************************
1996//******************************************************************************
1997BOOL OSLibDosDisconnectNamedPipe(DWORD hPipe)
1998{
1999 DWORD rc;
2000
2001 rc=DosDisConnectNPipe(hPipe);
2002
2003 dprintf(("DosDisConnectNPipe returned rc=%d",rc));
2004
2005 if(rc == NO_ERROR) {
2006 SetLastError(ERROR_SUCCESS_W);
2007 return (TRUE);
2008 }
2009 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
2010 return (FALSE);
2011}
2012//******************************************************************************
2013//******************************************************************************
2014BOOL OSLibDosWaitNamedPipe(LPCSTR lpszNamedPipeName,
2015 DWORD dwTimeout)
2016{
2017 LPSTR lpOS2Name;
2018 DWORD rc;
2019
2020 if (strstr(lpszNamedPipeName,"\\\\."))
2021 {
2022 // If pipe is created on the local machine
2023 // we must delete string \\. because
2024 // in Windows named pipes scheme is a \\.\PIPE\pipename
2025 // but in OS/2 only \PIPE\pipename
2026 lpOS2Name = (LPSTR)lpszNamedPipeName + 3;
2027 }
2028 else lpOS2Name = (LPSTR)lpszNamedPipeName;
2029
2030 rc=DosWaitNPipe(lpOS2Name,dwTimeout);
2031
2032 dprintf(("DosWaitNPipe returned rc=%d",rc));
2033
2034 if(rc == NO_ERROR) {
2035 SetLastError(ERROR_SUCCESS_W);
2036 return (TRUE);
2037 }
2038 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
2039
2040 return (FALSE);
2041}
2042//******************************************************************************
2043//******************************************************************************
2044BOOL isRoot(CHAR* name)
2045{
2046 if (name[1] == ':')
2047 {
2048 //local name (x:\)
2049 return (name[2] == 0) || !strchr(&name[3],'\\');
2050 } else if (name[0] == '\\')
2051 {
2052 //UNC name (\\resource\drive\)
2053 CHAR *drive,*dir;
2054
2055 drive = strchr(&name[2],'\\');
2056 if (!drive) return FALSE;
2057 dir = strchr(&drive[1],'\\');
2058 if (!dir) return TRUE;
2059 return !strchr(&dir[1],'\\');
2060 } else return FALSE; //unknown
2061}
2062//******************************************************************************
2063//******************************************************************************
2064inline CHAR system2DOSCharacter(CHAR ch)
2065{
2066 switch(ch)
2067 {
2068 case ' ':
2069 case '.':
2070 case '~':
2071 return '_';
2072
2073 default:
2074 return toupper(ch);
2075 }
2076}
2077
2078// TODO: not finished nor correct!!!!
2079VOID long2ShortName(CHAR* longName, CHAR* shortName)
2080{
2081 // check for uplink / root: "." and ".."
2082 if (longName[0] == '.')
2083 {
2084 // if ((strcmp(longName,".") == 0) || (strcmp(longName,"..") == 0))
2085 if (longName[1] == 0) // "."
2086 {
2087 shortName[0] = '.';
2088 shortName[1] = 0;
2089 return;
2090 }
2091
2092 if (longName[1] == '.' && longName[2] == 0) // ".."
2093 {
2094 shortName[0] = '.';
2095 shortName[1] = '.';
2096 shortName[2] = 0;
2097 return;
2098 }
2099 }
2100 else
2101 // check for empty name
2102 if(longName[0] == 0)
2103 {
2104 shortName[0] = 0;
2105 return;
2106 }
2107
2108 INT x;
2109 CHAR *source = longName;
2110
2111 // Test if longName is 8:3 compliant and simply copy
2112 // the filename.
2113 BOOL flag83 = TRUE;
2114
2115 // verify forbidden characters
2116 for (x = 0;
2117 (x < 8) &&
2118 (flag83 == TRUE);
2119 x++)
2120 {
2121 switch (*source)
2122 {
2123 case '.': // a period will cause the loop to abort!
2124 x=1000;
2125 break;
2126
2127 case '/': case '?':
2128 case '*': case ':':
2129 case '\\': case '"':
2130 case ' ':
2131 flag83 = FALSE;
2132 break;
2133 default:
2134 source++;
2135 break;
2136 }
2137 }
2138
2139 // verify we're on a period now
2140 if (flag83 == TRUE)
2141 if (*source != '.')
2142 flag83 = FALSE;
2143 else source++;
2144
2145 // verify extension
2146 if (flag83 == TRUE)
2147 for (INT y = 0;
2148 (y < 3) && (flag83 == TRUE);
2149 y++)
2150 {
2151 switch (*source)
2152 {
2153 case '/': case '?':
2154 case '*': case ':':
2155 case '\\': case '"':
2156 case ' ': case '.':
2157 flag83 = FALSE;
2158 break;
2159 }
2160 source++;
2161 }
2162
2163 // verify we're at the end of the string now
2164 if (flag83 == TRUE)
2165 if (*source != 0)
2166 flag83 = FALSE;
2167
2168 // OK, done
2169 if (flag83 == TRUE)
2170 {
2171 // we might not alter any character here, since
2172 // an app opening a specific file with an 8:3 "alias",
2173 // would surely fail.
2174 strcpy(shortName, longName);
2175
2176 return; // Done
2177 }
2178
2179
2180 // @@@PH
2181 shortName[0] = 0; // this function is disabled anyway ...
2182 return;
2183
2184 CHAR *dest = shortName;
2185 CHAR *ext = strrchr(longName,'.');
2186
2187 //CB: quick and dirty, real FILE~12.EXT is too slow
2188 //PH: We'd have to count the number of non-8:3-compliant files
2189 // within a directory. Or simpler: the number of files within
2190 // the current directory.
2191
2192 //8 character file name
2193 for (x = 0;x < 8;x++)
2194 {
2195 if ((source == ext) || (source[0] == 0)) break;
2196 dest[0] = system2DOSCharacter(source[0]);
2197 source++;
2198 dest++;
2199 }
2200
2201 if (source[0] == 0)
2202 {
2203 dest[0] = 0;
2204 return;
2205 }
2206
2207 if (source != ext)
2208 {
2209 //longName > 8 characters, insert ~1
2210 shortName[6] = '~';
2211 shortName[7] = '1';
2212 }
2213
2214 if (ext)
2215 {
2216 //add extension, 3 characters
2217 dest[0] = ext[0];
2218 dest++;
2219 ext++;
2220 for (x = 0;x < 3;x++)
2221 {
2222 if (ext[0] == 0) break;
2223 dest[0] = system2DOSCharacter(ext[0]);
2224 ext++;
2225 dest++;
2226 }
2227 }
2228 dest[0] = 0;
2229}
2230//******************************************************************************
2231//******************************************************************************
2232VOID translateFileResults(FILESTATUS3 *pResult,LPWIN32_FIND_DATAA pFind,CHAR* achName)
2233{
2234 CHAR* name;
2235
2236 pFind->dwReserved0 = pFind->dwReserved1 = 0;
2237 pFind->dwFileAttributes = pm2WinFileAttributes(pResult->attrFile);
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 name = strrchr(achName,'\\');
2246 if (name)
2247 {
2248 name++;
2249// strcpy(pFind->cFileName,name);
2250 OemToCharA( name, pFind->cFileName );
2251 }
2252 else
2253 pFind->cFileName[0] = 0;
2254
2255 long2ShortName(pFind->cFileName,pFind->cAlternateFileName);
2256}
2257
2258
2259VOID translateFindResults(FILEFINDBUF3 *pResult,LPWIN32_FIND_DATAA pFind)
2260{
2261 pFind->dwFileAttributes = pm2WinFileAttributes(pResult->attrFile);
2262 pFind->dwReserved0 = pFind->dwReserved1 = 0;
2263
2264 pmDateTimeToFileTime(&pResult->fdateCreation,&pResult->ftimeCreation,&pFind->ftCreationTime);
2265 pmDateTimeToFileTime(&pResult->fdateLastAccess,&pResult->ftimeLastAccess,&pFind->ftLastAccessTime);
2266 pmDateTimeToFileTime(&pResult->fdateLastWrite,&pResult->ftimeLastWrite,&pFind->ftLastWriteTime);
2267
2268 pFind->nFileSizeHigh = 0; //CB: fixme
2269 pFind->nFileSizeLow = pResult->cbFile;
2270// strcpy(pFind->cFileName,pResult->achName);
2271 OemToCharA( pResult->achName, pFind->cFileName );
2272 long2ShortName(pFind->cFileName,pFind->cAlternateFileName);
2273}
2274//******************************************************************************
2275//******************************************************************************
2276DWORD OSLibDosFindFirst(LPCSTR lpFileName,WIN32_FIND_DATAA* lpFindFileData)
2277{
2278 HDIR hDir = -1;
2279 ULONG attrs;
2280 FILEFINDBUF3 result;
2281 ULONG searchCount = 1;
2282
2283 attrs = FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY | FILE_ARCHIVED;
2284 result.achName[0] = 0;
2285
2286 ULONG oldmode = SetErrorMode(SEM_FAILCRITICALERRORS_W);
2287 char lOemFileName[260];
2288
2289 CharToOemA(lpFileName, lOemFileName);
2290
2291 APIRET rc = DosFindFirst((PSZ)lOemFileName,&hDir,attrs,&result,sizeof(result),&searchCount,FIL_STANDARD);
2292
2293 //check root: skip "." and ".." (HPFS, not on FAT)
2294 //check in OSLibDosFindNext not necessary: "." and ".." are the first two entries
2295 if ((rc == 0) && isRoot((LPSTR)lpFileName))
2296 {
2297 while ((strcmp(result.achName,".") == 0) ||
2298 (strcmp(result.achName,"..") == 0))
2299 {
2300 result.achName[0] = 0;
2301 searchCount = 1;
2302 APIRET rc = DosFindNext(hDir,&result,sizeof(result),&searchCount);
2303 if (rc)
2304 {
2305 DosFindClose(hDir);
2306 SetLastError(error2WinError(rc));
2307
2308 SetErrorMode(oldmode);
2309 return INVALID_HANDLE_VALUE_W;
2310 }
2311 }
2312 }
2313
2314 // enable i/o kernel exceptions again
2315 SetErrorMode(oldmode);
2316
2317 if(rc)
2318 {
2319 DosFindClose(hDir);
2320 SetLastError(error2WinError(rc));
2321 return INVALID_HANDLE_VALUE_W;
2322 }
2323 translateFindResults(&result,lpFindFileData);
2324 SetLastError(ERROR_SUCCESS_W);
2325 return hDir;
2326}
2327//******************************************************************************
2328// NOTE: returns "." and ".." in root
2329//******************************************************************************
2330DWORD OSLibDosFindFirstMulti(LPCSTR lpFileName,WIN32_FIND_DATAA *lpFindFileData,DWORD *count)
2331{
2332 HDIR hDir = -1;
2333 ULONG attrs;
2334 FILEFINDBUF3 *result,*data;
2335 ULONG searchCount = *count;
2336
2337 attrs = FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY | FILE_ARCHIVED;
2338 result = (FILEFINDBUF3*)malloc(searchCount*sizeof(FILEFINDBUF3));
2339
2340 ULONG oldmode = SetErrorMode(SEM_FAILCRITICALERRORS_W);
2341 char lOemFileName[260];
2342
2343 CharToOemA(lpFileName, lOemFileName);
2344 APIRET rc = DosFindFirst((PSZ)lOemFileName,&hDir,attrs,result,searchCount*sizeof(FILEFINDBUF3),&searchCount,FIL_STANDARD);
2345 SetErrorMode(oldmode);
2346 if (rc)
2347 {
2348 free(result);
2349 *count = 0;
2350 SetLastError(error2WinError(rc));
2351
2352 return INVALID_HANDLE_VALUE_W;
2353 }
2354
2355 data = result;
2356 for (int x = 0;x < searchCount;x++)
2357 {
2358 translateFindResults(data,&lpFindFileData[x]);
2359 data = (FILEFINDBUF3*)(((DWORD)data)+data->oNextEntryOffset);
2360 }
2361 free(result);
2362 *count = searchCount;
2363
2364 SetLastError(ERROR_SUCCESS_W);
2365 return hDir;
2366}
2367//******************************************************************************
2368//******************************************************************************
2369BOOL OSLibDosFindNext(DWORD hFindFile,WIN32_FIND_DATAA *lpFindFileData)
2370{
2371 FILEFINDBUF3 result;
2372 ULONG searchCount = 1;
2373
2374 APIRET rc = DosFindNext((HDIR)hFindFile,&result,sizeof(result),&searchCount);
2375 if (rc)
2376 {
2377 SetLastError(error2WinError(rc));
2378
2379 return FALSE;
2380 }
2381
2382 translateFindResults(&result,lpFindFileData);
2383 SetLastError(ERROR_SUCCESS_W);
2384 return TRUE;
2385}
2386//******************************************************************************
2387//******************************************************************************
2388BOOL OSLibDosFindNextMulti(DWORD hFindFile,WIN32_FIND_DATAA *lpFindFileData,DWORD *count)
2389{
2390 FILEFINDBUF3 *result,*data;
2391 ULONG searchCount = *count;
2392
2393 result = (FILEFINDBUF3*)malloc(searchCount*sizeof(FILEFINDBUF3));
2394 APIRET rc = DosFindNext((HDIR)hFindFile,result,searchCount*sizeof(FILEFINDBUF3),&searchCount);
2395 if (rc)
2396 {
2397 free(result);
2398 *count = 0;
2399 SetLastError(error2WinError(rc));
2400
2401 return FALSE;
2402 }
2403
2404 data = result;
2405 for (int x = 0;x < searchCount;x++)
2406 {
2407 translateFindResults(data,&lpFindFileData[x]);
2408 data = (FILEFINDBUF3*)(((DWORD)data)+data->oNextEntryOffset);
2409 }
2410 free(result);
2411 *count = searchCount;
2412
2413 SetLastError(ERROR_SUCCESS_W);
2414 return TRUE;
2415}
2416//******************************************************************************
2417//******************************************************************************
2418BOOL OSLibDosFindClose(DWORD hFindFile)
2419{
2420 APIRET rc = DosFindClose((HDIR)hFindFile);
2421 if (rc)
2422 {
2423 SetLastError(error2WinError(rc));
2424 return FALSE;
2425 }
2426
2427 SetLastError(ERROR_SUCCESS_W);
2428 return TRUE;
2429}
2430//******************************************************************************
2431#define FSATTACH_SIZE 256
2432//******************************************************************************
2433DWORD OSLibDosQueryVolumeFS(int drive, LPSTR lpFileSystemNameBuffer, DWORD nFileSystemNameSize)
2434{
2435 PFSQBUFFER2 fsinfo = (PFSQBUFFER2) alloca(FSATTACH_SIZE);
2436 ULONG cb = FSATTACH_SIZE;
2437 char drv[3] = "A:";
2438 char *fsname;
2439 APIRET rc;
2440
2441 if(lpFileSystemNameBuffer == NULL) {
2442 DebugInt3();
2443 return ERROR_INVALID_PARAMETER_W;
2444 }
2445 drv[0] = (char)('A' + drive - 1);
2446
2447 ULONG oldmode = SetErrorMode(SEM_FAILCRITICALERRORS_W);
2448 rc = DosQueryFSAttach(drv, 1, FSAIL_QUERYNAME, fsinfo, &cb);
2449 SetErrorMode(oldmode);
2450
2451 switch(rc) {
2452 case ERROR_INVALID_DRIVE:
2453 return ERROR_INVALID_DRIVE_W;
2454 case ERROR_NO_VOLUME_LABEL:
2455 return ERROR_NO_VOLUME_LABEL_W;
2456 case NO_ERROR:
2457 break;
2458 default:
2459 return ERROR_NOT_ENOUGH_MEMORY; //whatever
2460 }
2461
2462 fsname = (char *)&fsinfo->szName[0] + fsinfo->cbName + 1;
2463
2464 /* @@@PH 2000/08/10 CMD.EXE querys with nFileSystemNameSize == 0
2465 * however does NOT expect to receive an error.
2466 */
2467 strncpy(lpFileSystemNameBuffer,
2468 fsname,
2469 nFileSystemNameSize);
2470 /*
2471 if(strlen(fsname) < nFileSystemNameSize) {
2472 strcpy(lpFileSystemNameBuffer, fsname);
2473 }
2474 else return ERROR_BUFFER_OVERFLOW_W;
2475 */
2476 return ERROR_SUCCESS_W;
2477}
2478//******************************************************************************
2479typedef struct _FSINFOBUF
2480{
2481 ULONG ulVolser; /* Volume serial number */
2482 VOLUMELABEL vol; /* Volume lable */
2483} FSINFOBUF;
2484//******************************************************************************
2485DWORD OSLibDosQueryVolumeSerialAndName(int drive, LPDWORD lpVolumeSerialNumber,
2486 LPSTR lpVolumeNameBuffer, DWORD nVolumeNameSize)
2487{
2488 FSINFOBUF fsi;
2489 APIRET rc;
2490
2491 ULONG oldmode = SetErrorMode(SEM_FAILCRITICALERRORS_W);
2492 rc = DosQueryFSInfo(drive, FSIL_VOLSER, &fsi, sizeof(fsi));
2493 SetErrorMode(oldmode);
2494
2495 switch(rc) {
2496 case ERROR_INVALID_DRIVE:
2497 return ERROR_INVALID_DRIVE_W;
2498 case ERROR_NO_VOLUME_LABEL:
2499 return ERROR_NO_VOLUME_LABEL_W;
2500 case NO_ERROR:
2501 break;
2502 default:
2503 return ERROR_NOT_ENOUGH_MEMORY; //whatever
2504 }
2505
2506 if(lpVolumeSerialNumber) {
2507 *lpVolumeSerialNumber = fsi.ulVolser;
2508 }
2509 if(lpVolumeNameBuffer)
2510 {
2511 if(nVolumeNameSize > fsi.vol.cch) {
2512 strcpy(lpVolumeNameBuffer, (PCHAR)fsi.vol.szVolLabel);
2513 }
2514 else return ERROR_BUFFER_OVERFLOW_W;
2515 }
2516
2517 return ERROR_SUCCESS_W;
2518}
2519//******************************************************************************
2520//******************************************************************************
2521BOOL OSLibGetDiskFreeSpace(LPSTR lpRootPathName, LPDWORD lpSectorsPerCluster,
2522 LPDWORD lpBytesPerSector, LPDWORD lpNumberOfFreeClusters,
2523 LPDWORD lpTotalNumberOfClusters)
2524{
2525 ULONG diskNum;
2526 FSALLOCATE fsAlloc;
2527 APIRET rc;
2528
2529 if(lpRootPathName == 0)
2530 diskNum = 0;
2531 else
2532 if('A' <= *lpRootPathName && *lpRootPathName <= 'Z' )
2533 diskNum = *lpRootPathName - 'A' + 1;
2534 else
2535 if('a' <= *lpRootPathName && *lpRootPathName <= 'z' )
2536 diskNum = *lpRootPathName - 'a' + 1;
2537 else
2538 diskNum = 0;
2539
2540 ULONG oldmode = SetErrorMode(SEM_FAILCRITICALERRORS_W);
2541 rc = DosQueryFSInfo(diskNum, FSIL_ALLOC, &fsAlloc, sizeof(fsAlloc));
2542 SetErrorMode(oldmode);
2543
2544 if(rc == 0)
2545 {
2546 *lpSectorsPerCluster = fsAlloc.cSectorUnit;
2547 *lpBytesPerSector = fsAlloc.cbSector;
2548 *lpNumberOfFreeClusters = fsAlloc.cUnitAvail;
2549 *lpTotalNumberOfClusters = fsAlloc.cUnit;
2550 SetLastError(ERROR_SUCCESS_W);
2551 return TRUE;
2552 }
2553 SetLastError(error2WinError(rc));
2554 return FALSE;
2555}
2556//******************************************************************************
2557//******************************************************************************
2558BOOL OSLibDosGetDiskGeometry(HANDLE hDisk, DWORD cDisk, PVOID pdiskgeom)
2559{
2560 PDISK_GEOMETRY pGeom = (PDISK_GEOMETRY)pdiskgeom;
2561 BYTE param[2] = {0, 0};
2562 ULONG parsize = 2;
2563 BIOSPARAMETERBLOCK bpb;
2564 ULONG datasize = sizeof(bpb);
2565 APIRET rc;
2566
2567 dprintf(("OSLibDosGetDiskGeometry %x %d %x", hDisk, cDisk, pdiskgeom));
2568 param[1] = cDisk - 'A';
2569 rc = DosDevIOCtl((hDisk) ? hDisk : -1, IOCTL_DISK, DSK_GETDEVICEPARAMS, param, 2, &parsize, &bpb, sizeof(bpb), &datasize);
2570 if(rc == 0)
2571 {
2572 pGeom->SectorsPerTrack = bpb.usSectorsPerTrack;
2573 pGeom->BytesPerSector = bpb.usBytesPerSector;
2574 pGeom->TracksPerCylinder = 80; //TODO:!!!!!
2575 pGeom->Cylinders.u.LowPart = bpb.cCylinders;
2576 pGeom->Cylinders.u.HighPart = 0;
2577 switch(bpb.bDeviceType) {
2578 case DEVTYPE_48TPI:
2579 pGeom->MediaType = F5_360_512; //?????
2580 break;
2581 case DEVTYPE_96TPI:
2582 pGeom->MediaType = F5_1Pt2_512; //?????
2583 break;
2584 case DEVTYPE_35:
2585 pGeom->MediaType = F3_720_512;
2586 break;
2587 case DEVTYPE_8SD:
2588 case DEVTYPE_8DD:
2589 pGeom->MediaType = RemovableMedia;
2590 break;
2591 case DEVTYPE_FIXED:
2592 pGeom->MediaType = FixedMedia;
2593 break;
2594 case DEVTYPE_TAPE:
2595 pGeom->MediaType = RemovableMedia;
2596 break;
2597 case DEVTYPE_UNKNOWN: //others, include 1.44 3.5 inch disk drive
2598 pGeom->MediaType = F3_1Pt44_512;
2599 break;
2600 case 8: //RW optical disk
2601 pGeom->MediaType = RemovableMedia;
2602 break;
2603 case 9: //2.88 3.5 inch disk
2604 pGeom->MediaType = F3_2Pt88_512;
2605 break;
2606 }
2607 SetLastError(ERROR_SUCCESS_W);
2608 return TRUE;
2609 }
2610 dprintf(("OSLibDosGetDiskGeometry: error %d -> %d", rc, error2WinError(rc)));
2611 SetLastError(error2WinError(rc));
2612 return FALSE;
2613}
2614//******************************************************************************
2615
2616#define CDType 0x8000
2617#define FloppyType 0x4000
2618#define LanType 0x2000
2619#define LogicalType 0x1000
2620#define VDISKType 0x0800
2621#define OpticalType 0x0400
2622#define NonRemovable 0x01
2623
2624#define FirstDrive 0
2625#define B_Drive_0_Based 1
2626#define Base_1_offset 1
2627#define Binary_to_Printable 0x41
2628#define LastDrive 26
2629#define OpticalSectorsPerCluster 4
2630
2631#define DisketteCylinders 80
2632
2633#ifndef DEVTYPE_OPTICAL
2634#define DEVTYPE_OPTICAL 0x0008
2635#endif
2636
2637// used for input to logical disk Get device parms Ioctl
2638#pragma pack(1)
2639typedef struct
2640{
2641 UCHAR Infotype;
2642 UCHAR DriveUnit;
2643} DSKREQ;
2644
2645/*------------------------------------------------*
2646 * Cat 0x82, Func 0x60: Return Drive Letter Info *
2647 *------------------------------------------------*/
2648typedef struct DriveLetter_Data
2649{
2650 USHORT drive_count;
2651 USHORT first_drive_number;
2652} CDDRVLTR;
2653#pragma pack()
2654
2655
2656/**
2657 * Determin the type of a specific drive or the current drive.
2658 *
2659 * @returns DRIVE_UNKNOWN
2660 * DRIVE_NO_ROOT_DIR
2661 * DRIVE_CANNOTDETERMINE
2662 * DRIVE_DOESNOTEXIST
2663 * DRIVE_REMOVABLE
2664 * DRIVE_FIXED
2665 * DRIVE_REMOTE
2666 * DRIVE_CDROM
2667 * DRIVE_RAMDISK
2668 *
2669 * @param ulDrive Index of the drive which type we query.
2670 *
2671 * @status completely implemented and tested
2672 * @author Vitali Pelenyov <sunlover@anduin.net>
2673 * @author bird
2674 */
2675ULONG OSLibGetDriveType(ULONG ulDrive)
2676{
2677 ULONG cbParm;
2678 ULONG cbData;
2679 ULONG ulDriveNum = 0;
2680 ULONG ulDriveMap = 0;
2681 APIRET rc;
2682 ULONG ulDriveType;
2683
2684
2685 /*
2686 * Check if drive is present in the logical drive mask,
2687 */
2688 if ( DosQueryCurrentDisk(&ulDriveNum, &ulDriveMap)
2689 || !(ulDriveMap & (1 << ulDrive))
2690 )
2691 return DRIVE_DOESNOTEXIST_W;
2692
2693
2694 /*
2695 * Optimize floppy queries for A: and B:.
2696 * (I don't hope these are any subject of change.)
2697 */
2698 static ULONG ulFloppyMask = 0;
2699 if (ulFloppyMask & (1 << ulDrive))
2700 return DRIVE_REMOVABLE_W;
2701
2702
2703 /*
2704 * Check for CD drives
2705 * We don't have to this everytime. I mean, the os2cdrom.dmd is
2706 * exactly very dynamic when it comes to this info.
2707 */
2708 static CDDRVLTR cdDrvLtr = {0xffff, 0xffff};
2709 if (cdDrvLtr.drive_count == 0xffff)
2710 {
2711 HFILE hCDRom2;
2712 ULONG ulAction = 0;
2713
2714 if (DosOpen("\\DEV\\CD-ROM2$", &hCDRom2, &ulAction, 0,
2715 FILE_NORMAL, OPEN_ACTION_OPEN_IF_EXISTS,
2716 OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY, NULL)
2717 == NO_ERROR)
2718 {
2719 #define IOC_CDROM_2 0x82 /* from cdioctl.h (ddk, os2cdrom.dmd sample) */
2720 #define IOCD_RETURN_DRIVE_LETTER 0x60
2721 cbData = sizeof(cdDrvLtr);
2722 rc = DosDevIOCtl(hCDRom2,
2723 IOC_CDROM_2,
2724 IOCD_RETURN_DRIVE_LETTER,
2725 NULL, 0, NULL,
2726 (PVOID)&cdDrvLtr, sizeof(cdDrvLtr), &cbData);
2727 DosClose(hCDRom2);
2728 }
2729 }
2730
2731
2732 /*
2733 * Is the drive present?? Lets the the BPB to check this.
2734 * this should be a pretty speedy call if I'm not much mistaken.
2735 */
2736 BIOSPARAMETERBLOCK bpb = {0};
2737 DSKREQ DskReq;
2738 DskReq.Infotype = 0;
2739 DskReq.DriveUnit = (UCHAR)ulDrive;
2740 cbParm = sizeof(DskReq);
2741 cbData = sizeof(bpb);
2742 if (DosDevIOCtl(-1, IOCTL_DISK, DSK_GETDEVICEPARAMS,
2743 (PVOID)&DskReq, sizeof(DskReq), &cbParm,
2744 (PVOID)&bpb, sizeof(BIOSPARAMETERBLOCK), &cbData)
2745 == NO_ERROR)
2746 {
2747 if (bpb.bDeviceType == 0 && bpb.fsDeviceAttr == 0)
2748 bpb.fsDeviceAttr = LanType; // fix for LAN type drives
2749 }
2750 else
2751 bpb.fsDeviceAttr = LanType; //could be a LAN drive - could it??
2752
2753
2754 /*
2755 * This is a CDROM/DVD drive
2756 *
2757 * Fix: When the cdrom is not last drive letter that
2758 * sometimes reports wrong index, have to check
2759 * that device type can be a CDROM one.
2760 */
2761 if ( cdDrvLtr.drive_count > 0
2762 && (bpb.bDeviceType == DEVTYPE_UNKNOWN || bpb.bDeviceType == DEVTYPE_OPTICAL) // Other or RW optical
2763 && ulDrive >= cdDrvLtr.first_drive_number
2764 && ulDrive < cdDrvLtr.first_drive_number + cdDrvLtr.drive_count
2765 )
2766 bpb.fsDeviceAttr |= CDType;
2767
2768
2769 if (bpb.bDeviceType || bpb.fsDeviceAttr == LanType)
2770 {
2771 if ((bpb.fsDeviceAttr & (CDType | NonRemovable)) == 0)
2772 { // if the device is removable and NOT a CD
2773 CHAR szDevName[4] = "A:";
2774 PFSQBUFFER2 pfsqbuf2;
2775
2776 szDevName[0] += ulDrive;
2777 cbData = sizeof(PFSQBUFFER2) + 3 * CCHMAXPATH;
2778 pfsqbuf2 = (PFSQBUFFER2)malloc(cbData);
2779 DosError(FERR_DISABLEEXCEPTION | FERR_DISABLEHARDERR); // disable error popups
2780 rc = DosQueryFSAttach(&szDevName[0], 0L, FSAIL_QUERYNAME, pfsqbuf2, &cbData);
2781 if (rc == NO_ERROR)
2782 {
2783 if (pfsqbuf2->iType == FSAT_REMOTEDRV)
2784 bpb.fsDeviceAttr |= LanType;
2785 else if (pfsqbuf2->iType == FSAT_LOCALDRV)
2786 {
2787 PSZ pszFSName = (PSZ)pfsqbuf2->szName + pfsqbuf2->cbName;
2788 if (!strcmp(pszFSName, "FAT"))
2789 {
2790 // device is a removable FAT drive, so it MUST be diskette
2791 // as Optical has another name as does LAN and SRVIFS
2792 if (bpb.bSectorsPerCluster != OpticalSectorsPerCluster)
2793 bpb.fsDeviceAttr |= FloppyType;
2794 else
2795 bpb.fsDeviceAttr |= OpticalType;
2796 }
2797 /*
2798 * CDROM detection fix
2799 */
2800 else
2801 {
2802 // device is removable non-FAT, maybe it is CD?
2803 if ( bpb.bDeviceType == DEVTYPE_UNKNOWN
2804 && bpb.bMedia == 5
2805 && bpb.usBytesPerSector > 512
2806 )
2807 bpb.fsDeviceAttr |= CDType;
2808 }
2809 // CDROM detection fix
2810 }
2811 }
2812 else // must be no media or audio only (for CDs at least)
2813 {
2814 if (bpb.cCylinders <= DisketteCylinders) // floppies will always be 80
2815 {
2816 // or less cylinders
2817 if (bpb.bSectorsPerCluster != OpticalSectorsPerCluster)
2818 bpb.fsDeviceAttr |= FloppyType;
2819 else
2820 bpb.fsDeviceAttr |= OpticalType;
2821 }
2822 }
2823
2824 //Enable error popups again
2825 DosError(FERR_ENABLEEXCEPTION | FERR_ENABLEHARDERR);
2826
2827 free(pfsqbuf2);
2828 }
2829 else
2830 {// non removable or CD type. maybe RAM disk
2831 if (!(bpb.fsDeviceAttr & CDType)) // if NOT CD
2832 {
2833 if (bpb.cFATs == 1) // is there only one FAT?
2834 bpb.fsDeviceAttr |= VDISKType; // -> RAM disk
2835 }
2836 }
2837 }
2838
2839
2840 /*
2841 * Determin return value.
2842 */
2843 if (bpb.fsDeviceAttr & FloppyType)
2844 {
2845 ulDriveType = DRIVE_REMOVABLE_W;
2846 /* update floppy cache if A or B */
2847 if (ulDrive <= 1)
2848 ulFloppyMask |= 1 << ulDrive;
2849 }
2850 else if (bpb.fsDeviceAttr & CDType)
2851 ulDriveType = DRIVE_CDROM_W;
2852 else if (bpb.fsDeviceAttr & LanType)
2853 ulDriveType = DRIVE_REMOTE_W;
2854 else if (bpb.fsDeviceAttr & VDISKType)
2855 ulDriveType = DRIVE_RAMDISK_W;
2856 else if (bpb.fsDeviceAttr & OpticalType || bpb.bDeviceType == DEVTYPE_OPTICAL)
2857 ulDriveType = DRIVE_FIXED_W;
2858 else if (bpb.bDeviceType == DEVTYPE_FIXED)
2859 ulDriveType = DRIVE_FIXED_W;
2860 else
2861 ulDriveType = DRIVE_UNKNOWN_W;
2862
2863 return ulDriveType;
2864}
2865//******************************************************************************
2866//Returns bit map where with the mapping of the logical drives
2867//******************************************************************************
2868ULONG OSLibGetLogicalDrives()
2869{
2870 ULONG ulDriveNum = 0; /* Drive number (A=1, B=2, C=3, ...) */
2871 ULONG ulDriveMap = 0; /* Mapping of valid drives */
2872 APIRET rc;
2873
2874 rc = DosQueryCurrentDisk(&ulDriveNum, &ulDriveMap);
2875 if(rc) {
2876 DebugInt3();
2877 SetLastError(error2WinError(rc));
2878 return 0;
2879 }
2880 return ulDriveMap;
2881}
2882//******************************************************************************
2883//******************************************************************************
2884ULONG OSLibDosQueryCurrentDisk()
2885
2886{
2887 ULONG ulDriveNum = 0; /* Drive number (A=1, B=2, C=3, ...) */
2888 ULONG ulDriveMap = 0; /* Mapping of valid drives */
2889 APIRET rc;
2890
2891 rc = DosQueryCurrentDisk(&ulDriveNum, &ulDriveMap);
2892 if(rc) {
2893 DebugInt3();
2894 SetLastError(error2WinError(rc));
2895 return 0;
2896 }
2897 return ulDriveNum;
2898}
2899//******************************************************************************
2900//******************************************************************************
2901BOOL OSLibDosCreatePipe(PHANDLE phfRead,
2902 PHANDLE phfWrite,
2903 LPSECURITY_ATTRIBUTES lpsa,
2904 DWORD dwSize)
2905{
2906 APIRET rc;
2907
2908 dprintf(("DosCreatePipe(%08xh,%08xh,%08xh)\n",
2909 phfRead,
2910 phfWrite,
2911 dwSize));
2912
2913 // select default buffer size
2914 if (dwSize == 0)
2915 dwSize = 4096;
2916
2917 rc = DosCreatePipe(phfRead,
2918 phfWrite,
2919 dwSize);
2920 dprintf(("DosCreatePipe rc=%d",rc));
2921 if (rc)
2922 {
2923 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER_W));
2924 return -1; // INVALID_HANDLE_VALUE
2925 }
2926 SetLastError(ERROR_SUCCESS_W);
2927 return NO_ERROR;
2928}
2929//******************************************************************************
2930//******************************************************************************
2931DWORD OSLibDosDevIOCtl( DWORD hFile, DWORD dwCat, DWORD dwFunc,
2932 PVOID pParm, DWORD dwParmMaxLen, DWORD *pdwParmLen,
2933 PVOID pData, DWORD dwDataMaxLen, DWORD *pdwDataLen)
2934{
2935 APIRET rc;
2936 PVOID pTiledParm = pParm;
2937 BOOL flagTiledParm = FALSE;
2938 PVOID pTiledData = pData;
2939 BOOL flagTiledData = FALSE;
2940
2941#define MEM_TILED_CEILING 0x1fffffff
2942
2943 // bounce buffer support
2944 // make sure no parameter or data buffer can pass the tiled memory region
2945 // barrier (usually 512MB). OS/2 kernel does not correctly translate these
2946 // addresses to a 16:16 address used in device driver land. In fact,
2947 // DosDevIOCtl is not a high memory enabled API!
2948
2949 if (pTiledParm && (((DWORD)pTiledParm + max(dwParmMaxLen, *pdwParmLen)) > MEM_TILED_CEILING))
2950 {
2951 rc = DosAllocMem(&pTiledParm, dwParmMaxLen, PAG_READ | PAG_WRITE);
2952 if (rc)
2953 goto _exit_ioctl;
2954
2955 flagTiledParm = TRUE;
2956 }
2957
2958 if (pTiledData && (((DWORD)pTiledData + max(dwDataMaxLen, *pdwDataLen)) > MEM_TILED_CEILING))
2959 {
2960 rc = DosAllocMem(&pTiledData, dwDataMaxLen, PAG_READ | PAG_WRITE);
2961 if (rc)
2962 goto _exit_ioctl;
2963
2964 flagTiledData = TRUE;
2965 }
2966
2967 // copy data from real buffers to
2968 // bounce buffers if necessary
2969 if (pTiledParm != pParm)
2970 memcpy(pTiledParm, pParm, *pdwParmLen);
2971
2972 if (pTiledData != pData)
2973 memcpy(pTiledData, pData, *pdwDataLen);
2974
2975
2976 rc = DosDevIOCtl( (HFILE)hFile, dwCat, dwFunc,
2977 pParm, dwParmMaxLen, pdwParmLen,
2978 pData, dwDataMaxLen, pdwDataLen);
2979
2980 // copy data from bounce buffers to real
2981 // target buffers if necessary
2982 if (pTiledParm != pParm)
2983 memcpy(pParm, pTiledParm, *pdwParmLen);
2984
2985 if (pTiledData != pData)
2986 memcpy(pData, pTiledData, *pdwDataLen);
2987
2988
2989 _exit_ioctl:
2990
2991 // deallocate bounce buffers
2992 if (flagTiledParm)
2993 DosFreeMem(pTiledParm);
2994
2995 if (flagTiledData)
2996 DosFreeMem(pTiledData);
2997
2998 rc = error2WinError(rc, ERROR_INVALID_HANDLE);
2999 SetLastError(rc);
3000 return (DWORD)rc;
3001}
3002
3003/**
3004 * Pure wrapper for DosQueryModulName which returns the OS/2 returncode.
3005 * @returns Returncode from DosQueryModuleName.
3006 * @param hModule Handle of the module which name we query.
3007 * @param cchName Length of the output name buffer.
3008 * @param pszname Pointer to the output name buffer.
3009 * @status Completely implemented.
3010 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
3011 */
3012ULONG OSLibDosQueryModuleName(ULONG hModule, int cchName, char *pszName)
3013{
3014 return DosQueryModuleName(hModule, cchName, pszName);
3015}
3016
3017
3018HINSTANCE OSLibDosLoadModule(LPSTR szModName)
3019{
3020 APIRET rc;
3021 HMODULE hModule = NULLHANDLE;
3022 char name[ CCHMAXPATH ];
3023
3024 rc = DosLoadModule(name, CCHMAXPATH, szModName, &hModule);
3025 if(rc) {
3026 SetLastError(error2WinError(rc,ERROR_FILE_NOT_FOUND));
3027 return 0;
3028 }
3029 SetLastError(ERROR_SUCCESS_W);
3030 return hModule;
3031}
3032//******************************************************************************
3033//******************************************************************************
3034void OSLibDosFreeModule(HINSTANCE hinst)
3035{
3036 DosFreeModule(hinst);
3037}
3038//******************************************************************************
3039//******************************************************************************
3040ULONG OSLibDosQuerySysInfo(ULONG iStart, ULONG iLast, PVOID pBuf, ULONG cbBuf)
3041{
3042 APIRET rc;
3043
3044 rc = DosQuerySysInfo(iStart, iLast, pBuf, cbBuf);
3045 SetLastError(error2WinError(rc,ERROR_INVALID_HANDLE));
3046 return rc;
3047}
3048//******************************************************************************
3049//returned length is number of characters required or used for current dir
3050//*excluding* terminator
3051//******************************************************************************
3052ULONG OSLibDosQueryDir(DWORD length, LPSTR lpszCurDir)
3053{
3054 ULONG drivemap, currentdisk, len;
3055 char *lpszCurDriveAndDir = lpszCurDir +3;
3056 APIRET rc;
3057
3058 len = (length > 3) ? length - 3 : 0;
3059
3060 rc = DosQueryCurrentDir(0, lpszCurDriveAndDir, &len);
3061 if(rc != ERROR_BUFFER_OVERFLOW)
3062 {
3063 if(rc)
3064 {
3065 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER));
3066 return 0;
3067 }
3068 len = strlen(lpszCurDriveAndDir) + 3;
3069
3070 // Dir returned by DosQueryCurDir doesn't include drive, so add it
3071 DosQueryCurrentDisk(&currentdisk, &drivemap);
3072
3073 if(isupper(lpszCurDir[3])) {
3074 lpszCurDir[0] = (char)('A' - 1 + currentdisk);
3075 }
3076 else lpszCurDir[0] = (char)('a' - 1 + currentdisk);
3077
3078 lpszCurDir[1] = ':';
3079 lpszCurDir[2] = '\\';
3080 }
3081 else len += 3; // + 3 since DosQueryCurDir doesn't include drive
3082
3083 SetLastError(ERROR_SUCCESS_W);
3084 return len;
3085}
3086//******************************************************************************
3087//******************************************************************************
3088BOOL OSLibDosBeep(DWORD ulFreq, DWORD ulDuration)
3089{
3090 APIRET rc;
3091
3092 if (ulDuration == -1)
3093 {
3094 SetLastError(ERROR_NOT_SUPPORTED_W);
3095 return FALSE;
3096 }
3097 rc = DosBeep(ulFreq, ulDuration);
3098 SetLastError(error2WinError(rc,ERROR_INVALID_HANDLE));
3099
3100 return (rc == 0);
3101}
3102//******************************************************************************
3103//******************************************************************************
3104ULONG OSLibDosGetModuleFileName(HMODULE hModule, LPTSTR lpszPath, DWORD cchPath)
3105{
3106 PTIB pTIB;
3107 PPIB pPIB;
3108 APIRET rc;
3109
3110 if(hModule == -1 || hModule == 0)
3111 {
3112 DosGetInfoBlocks(&pTIB, &pPIB);
3113 hModule = pPIB->pib_hmte;
3114 }
3115 *lpszPath = 0;
3116 rc = DosQueryModuleName(hModule, cchPath, lpszPath);
3117
3118 DWORD len = strlen(lpszPath);
3119 SetLastError(error2WinError(rc,ERROR_INVALID_HANDLE));
3120 return len;
3121}
3122//******************************************************************************
3123//******************************************************************************
3124ULONG OSLibDosGetProcAddress(HMODULE hModule, LPCSTR lpszProc)
3125{
3126 APIRET rc;
3127 PFN pfn = NULL;
3128 ULONG ordinal = (((ULONG)lpszProc) <= 0xFFFF) ? (ULONG)lpszProc : 0;
3129 HMODULE hmod = (HMODULE)hModule;
3130
3131 rc = DosQueryProcAddr( hmod, ordinal, (PSZ)lpszProc, &pfn );
3132 if(rc == ERROR_INVALID_HANDLE && pfn == NULL) {
3133 CHAR pszError[32], pszModule[CCHMAXPATH];
3134
3135 if(DosQueryModuleName( hmod, CCHMAXPATH, pszModule ) == 0 &&
3136 DosLoadModule( pszError, 32, pszModule, &hmod ) == 0)
3137 {
3138 rc = DosQueryProcAddr(hmod, ordinal, (PSZ)lpszProc, &pfn);
3139 }
3140 }
3141 SetLastError(error2WinError(rc,ERROR_INVALID_HANDLE));
3142
3143 return (ULONG)pfn;
3144}
3145//******************************************************************************
3146//******************************************************************************
3147BOOL OSLibDosSetThreadAffinity(DWORD dwThreadAffinityMask)
3148{
3149 static PROC_DosSetThreadAffinity pfnDosSetThreadAffinity = NULL;
3150 static BOOL fInit = FALSE;
3151 MPAFFINITY mask;
3152 APIRET rc;
3153
3154 if(fInit == FALSE && pfnDosSetThreadAffinity == NULL)
3155 {
3156 ULONG nrCPUs;
3157
3158 rc = DosQuerySysInfo(QSV_NUMPROCESSORS, QSV_NUMPROCESSORS, &nrCPUs, sizeof(nrCPUs));
3159 if (rc != 0 || nrCPUs == 1)
3160 {//not supported
3161 fInit = TRUE;
3162 SetLastError(ERROR_SUCCESS_W);
3163 return TRUE;
3164 }
3165
3166 HMODULE hDoscalls;
3167 if(DosQueryModuleHandle("DOSCALLS", &hDoscalls) == NO_ERROR) {
3168 DosQueryProcAddr(hDoscalls, 564, NULL, (PFN *)&pfnDosSetThreadAffinity);
3169 }
3170 fInit = TRUE;
3171 }
3172 if(fInit && pfnDosSetThreadAffinity == NULL) {
3173 SetLastError(ERROR_SUCCESS_W);
3174 return TRUE;
3175 }
3176 USHORT sel = RestoreOS2FS();
3177
3178 mask.mask[0] = dwThreadAffinityMask;
3179 mask.mask[1] = 0; //TODO: this might not be a good idea, but then again, not many people have > 32 cpus
3180
3181 rc = pfnDosSetThreadAffinity(&mask);
3182 SetFS(sel);
3183
3184 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER));
3185 return (rc == NO_ERROR);
3186}
3187//******************************************************************************
3188//******************************************************************************
3189BOOL OSLibDosQueryAffinity(DWORD fMaskType, DWORD *pdwThreadAffinityMask)
3190{
3191 static PROC_DosQueryThreadAffinity pfnDosQueryThreadAffinity = NULL;
3192 static BOOL fInit = FALSE;
3193 MPAFFINITY mask;
3194 APIRET rc;
3195
3196 if(fInit == FALSE && pfnDosQueryThreadAffinity == NULL)
3197 {
3198 ULONG nrCPUs;
3199
3200 rc = DosQuerySysInfo(QSV_NUMPROCESSORS, QSV_NUMPROCESSORS, &nrCPUs, sizeof(nrCPUs));
3201 if (rc != 0 || nrCPUs == 1)
3202 {//not supported
3203 fInit = TRUE;
3204 *pdwThreadAffinityMask = 1;
3205 SetLastError(ERROR_SUCCESS_W);
3206 return TRUE;
3207 }
3208
3209 HMODULE hDoscalls;
3210 if(DosQueryModuleHandle("DOSCALLS", &hDoscalls) == NO_ERROR) {
3211 DosQueryProcAddr(hDoscalls, 563, NULL, (PFN *)&pfnDosQueryThreadAffinity);
3212 }
3213 fInit = TRUE;
3214 }
3215 if(fInit && pfnDosQueryThreadAffinity == NULL) {
3216 *pdwThreadAffinityMask = 1;
3217 SetLastError(ERROR_SUCCESS_W);
3218 return TRUE;
3219 }
3220
3221 ULONG scope = (fMaskType == MASK_SYSTEM) ? AFNTY_SYSTEM : AFNTY_THREAD;
3222
3223 USHORT sel = RestoreOS2FS();
3224
3225 rc = pfnDosQueryThreadAffinity(scope, &mask);
3226 SetFS(sel);
3227
3228 if(rc == NO_ERROR) {
3229 *pdwThreadAffinityMask = mask.mask[0];
3230 }
3231
3232 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER));
3233 return (rc == NO_ERROR);
3234}
3235//******************************************************************************
3236//******************************************************************************
3237DWORD OSLibDosSetPriority(ULONG tid, int priority)
3238{
3239 DWORD ret, os2priorityclass;
3240 LONG os2prioritydelta;
3241 APIRET rc;
3242
3243 switch(priority)
3244 {
3245 case THREAD_PRIORITY_IDLE_W:
3246 os2priorityclass = PRTYC_IDLETIME;
3247 os2prioritydelta = 0;
3248 break;
3249 case THREAD_PRIORITY_LOWEST_W:
3250 os2priorityclass = PRTYC_REGULAR;
3251 os2prioritydelta = PRTYD_MINIMUM;
3252 break;
3253 case THREAD_PRIORITY_BELOW_NORMAL_W:
3254 os2priorityclass = PRTYC_REGULAR;
3255 os2prioritydelta = -15;
3256 break;
3257 case THREAD_PRIORITY_NORMAL_W:
3258 os2priorityclass = PRTYC_REGULAR;
3259 os2prioritydelta = 0;
3260 break;
3261 case THREAD_PRIORITY_ABOVE_NORMAL_W:
3262 os2priorityclass = PRTYC_REGULAR;
3263 os2prioritydelta = 15;
3264 break;
3265 case THREAD_PRIORITY_HIGHEST_W:
3266 os2priorityclass = PRTYC_REGULAR;
3267 os2prioritydelta = PRTYD_MAXIMUM;
3268 break;
3269 case THREAD_PRIORITY_TIME_CRITICAL_W:
3270 os2priorityclass = PRTYC_TIMECRITICAL;
3271 os2prioritydelta = 0;
3272 break;
3273 default:
3274 dprintf(("!WARNING!: Invalid priority!!"));
3275 SetLastError(ERROR_INVALID_PARAMETER_W);
3276 return ERROR_INVALID_PARAMETER_W;
3277 }
3278 rc = DosSetPriority(PRTYS_THREAD, os2priorityclass, os2prioritydelta, tid);
3279 ret = error2WinError(rc, ERROR_INVALID_PARAMETER);
3280 SetLastError(ret);
3281 return ret;
3282}
3283//******************************************************************************
3284//******************************************************************************
3285void OSLibDosSleep(ULONG msecs)
3286{
3287 DosSleep(msecs);
3288}
3289//******************************************************************************
3290//******************************************************************************
3291void OSLibDosExitThread(ULONG retcode)
3292{
3293 DosExit(EXIT_THREAD, retcode);
3294}
3295//******************************************************************************
3296//******************************************************************************
3297DWORD OSLibDosDevConfig(PVOID pdevinfo,
3298 ULONG item)
3299{
3300 return (DWORD)DosDevConfig(pdevinfo, item);
3301}
3302//******************************************************************************
3303//******************************************************************************
Note: See TracBrowser for help on using the repository browser.