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

Last change on this file since 8600 was 8600, checked in by sandervl, 23 years ago

Export OSLibDosDevIOCtl

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