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

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

OSLibGetDriveTye fix for floppy drives

File size: 106.9 KB
Line 
1/* $Id: oslibdos.cpp,v 1.106 2002-06-26 11:08:47 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 USHORT dosTime, dosDate;
879 BOOL ret;
880 FILETIME dummy;
881
882 dosTime = *(USHORT*)pTime;
883 dosDate = *(USHORT*)pDate;
884
885 ret = DosDateTimeToFileTime(dosDate, dosTime, &dummy);
886 if(ret == FALSE) {
887 return FALSE;
888 }
889 //time we get from OS2 is local time; win32 expects file time (UTC)
890 ret = LocalFileTimeToFileTime(&dummy, pFT);
891 return ret;
892}
893//******************************************************************************
894//******************************************************************************
895#define NOT_NORMAL (FILE_ATTRIBUTE_READONLY_W | \
896 FILE_ATTRIBUTE_HIDDEN_W | \
897 FILE_ATTRIBUTE_SYSTEM_W | \
898 FILE_ATTRIBUTE_ARCHIVE_W)
899
900inline DWORD pm2WinFileAttributes(DWORD attrFile)
901{
902 DWORD res = 0;
903
904 if (!(attrFile & NOT_NORMAL))
905 res |= FILE_ATTRIBUTE_NORMAL_W;
906 if (attrFile & FILE_READONLY)
907 res |= FILE_ATTRIBUTE_READONLY_W;
908 if (attrFile & FILE_HIDDEN)
909 res |= FILE_ATTRIBUTE_HIDDEN_W;
910 if (attrFile & FILE_SYSTEM)
911 res |= FILE_ATTRIBUTE_SYSTEM_W;
912 if (attrFile & FILE_DIRECTORY)
913 res |= FILE_ATTRIBUTE_DIRECTORY_W;
914 if (attrFile & FILE_ARCHIVED)
915 res |= FILE_ATTRIBUTE_ARCHIVE_W;
916
917 //CB: not used: FILE_ATTRIBUTE_COMPRESSED_W
918 //PH: NT server will serve appropriate sizes for compressed files
919 // over network. So if realSize < allocatedSize, the file must
920 // be compressed.
921
922 return res;
923}
924//******************************************************************************
925//******************************************************************************
926BOOL OSLibDosGetFileAttributesEx(PSZ pszName,
927 ULONG ulDummy,
928 PVOID pBuffer)
929{
930 APIRET rc; /* API return code */
931 FILESTATUS3 fs3; /* file information structure */
932 LPWIN32_FILE_ATTRIBUTE_DATA lpFad = (LPWIN32_FILE_ATTRIBUTE_DATA) pBuffer;
933
934 // Note: we only handle standard "GetFileExInfoStandard" requests
935 rc = DosQueryPathInfo(pszName, /* query the file information */
936 FIL_STANDARD,
937 &fs3,
938 sizeof(fs3));
939 if (rc != NO_ERROR) /* check for errors */
940 return FALSE; /* raise error condition */
941
942 // convert structure
943 lpFad->dwFileAttributes = pm2WinFileAttributes(fs3.attrFile);
944 pmDateTimeToFileTime(&fs3.fdateCreation, &fs3.ftimeCreation, &lpFad->ftCreationTime);
945 pmDateTimeToFileTime(&fs3.fdateLastAccess, &fs3.ftimeLastAccess, &lpFad->ftLastAccessTime);
946 pmDateTimeToFileTime(&fs3.fdateLastWrite, &fs3.ftimeLastWrite, &lpFad->ftLastWriteTime);
947
948 /* @@@PH we might add Aurora support ...
949 lpFad->nFileSizeHigh = info.nFileSizeHigh;
950 */
951 lpFad->nFileSizeHigh = 0;
952 lpFad->nFileSizeLow = fs3.cbFile;
953
954 return TRUE;
955}
956//******************************************************************************
957DWORD WIN32API GetEnvironmentVariableA(LPCSTR, LPSTR, DWORD );
958//******************************************************************************
959DWORD OSLibDosSearchPath(DWORD cmd, char *path, char *name, char *full_name,
960 DWORD length_fullname)
961{
962 switch(cmd) {
963 case OSLIB_SEARCHDIR:
964 if(DosSearchPath(SEARCH_IGNORENETERRS, path,
965 name, full_name, length_fullname) != 0) {
966 return 0;
967 }
968 return strlen(full_name);
969
970
971 case OSLIB_SEARCHCURDIR:
972 if(DosSearchPath(SEARCH_IGNORENETERRS | SEARCH_CUR_DIRECTORY, path,
973 name, full_name, length_fullname) != 0) {
974 return 0;
975 }
976 return strlen(full_name);
977
978 case OSLIB_SEARCHFILE:
979 {
980 FILESTATUS3 fileinfo;
981
982 if(DosQueryPathInfo(name, FIL_STANDARD, &fileinfo, sizeof(fileinfo)) != 0) {
983 return 0;
984 }
985 strncpy(full_name, name, length_fullname);
986 full_name[length_fullname-1] = 0;
987 return strlen(full_name);
988 }
989
990 case OSLIB_SEARCHENV:
991 {
992 LPSTR envstring;
993 int envsize;
994 CHAR szResult[CCHMAXPATH];
995
996 envsize = GetEnvironmentVariableA(path, NULL, 0);
997 envstring = (LPSTR)malloc(envsize+1);
998 GetEnvironmentVariableA(path, envstring, envsize);
999 if(DosSearchPath(SEARCH_IGNORENETERRS, envstring,
1000 name, szResult, sizeof(szResult)) != 0) {
1001 free(envstring);
1002 return 0;
1003 }
1004 free(envstring);
1005 strcpy(full_name, szResult);
1006 return strlen(full_name);
1007 }
1008 }
1009 return 0;
1010}
1011//******************************************************************************
1012//******************************************************************************
1013DWORD OSLibDosQueryPathInfo(CHAR *pszPathName,
1014 ULONG ulInfoLevel,
1015 PVOID pInfoBuf,
1016 ULONG cbInfoBuf)
1017{
1018 APIRET rc = DosQueryPathInfo( pszPathName, ulInfoLevel,
1019 pInfoBuf, cbInfoBuf );
1020
1021 if(rc == ERROR_TOO_MANY_OPEN_FILES)
1022 {
1023 LONG reqCount = 2;
1024 ULONG maxFiles;
1025
1026 if(DosSetRelMaxFH(&reqCount, &maxFiles) == NO_ERROR)
1027 rc = DosQueryPathInfo(pszPathName, ulInfoLevel,
1028 pInfoBuf, cbInfoBuf );
1029 }
1030 return rc;
1031}
1032//******************************************************************************
1033//******************************************************************************
1034DWORD OSLibDosCreateFile(CHAR *lpszFile,
1035 DWORD fuAccess,
1036 DWORD fuShare,
1037 LPSECURITY_ATTRIBUTES lpSecurityAttributes,
1038 DWORD fuCreate,
1039 DWORD fuAttrFlags,
1040 HANDLE hTemplateFile)
1041{
1042 HFILE hFile;
1043 ULONG actionTaken = 0;
1044 LONGLONG fileSize = {0};
1045 ULONG fileAttr = FILE_NORMAL;
1046 ULONG openFlag = 0;
1047 ULONG openMode = 0;
1048 APIRET rc = ERROR_NOT_ENOUGH_MEMORY;;
1049
1050 //TODO: lpSecurityAttributes (inheritance)
1051
1052 if(fuAttrFlags & FILE_ATTRIBUTE_ARCHIVE_W)
1053 fileAttr |= FILE_ARCHIVED;
1054 if(fuAttrFlags & FILE_ATTRIBUTE_HIDDEN_W)
1055 fileAttr |= FILE_HIDDEN;
1056 if(fuAttrFlags & FILE_ATTRIBUTE_SYSTEM_W)
1057 fileAttr |= FILE_SYSTEM;
1058 if(fuAttrFlags & FILE_ATTRIBUTE_READONLY_W)
1059 fileAttr |= FILE_READONLY;
1060 // TODO: FILE_ATTRIBUTE_TEMPORARY_W
1061
1062 switch(fuCreate)
1063 {
1064 case CREATE_NEW_W:
1065 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_FAIL_IF_EXISTS;
1066 break;
1067 case CREATE_ALWAYS_W:
1068 /* kso 2000-11-26: Not sure if OPEN_ACTION_REPLACE_IF_EXISTS is correct here! It is correct according to
1069 * MSDN, but not according to "The Win32 API SuperBible". Anyway I haven't got time to check it out in
1070 * NT now.
1071 * The problem is that OPEN_ACTION_REPLACE_IF_EXISTS requires write access. It failes with
1072 * rc = ERROR_ACCESS_DENIED (5). Quick fix, use OPEN_IF_EXIST if readonly access.
1073 */
1074 if (fuAccess & GENERIC_WRITE_W)
1075 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS;
1076 else
1077 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
1078 break;
1079 case OPEN_EXISTING_W:
1080 openFlag |= OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
1081 break;
1082 case OPEN_ALWAYS_W:
1083 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
1084 break;
1085 case TRUNCATE_EXISTING_W:
1086 openFlag |= OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS;
1087 break;
1088 }
1089
1090 if(fuAttrFlags & FILE_FLAG_WRITE_THROUGH_W) openMode |= OPEN_FLAGS_WRITE_THROUGH;
1091 if(fuAttrFlags & FILE_FLAG_NO_BUFFERING_W) openMode |= OPEN_FLAGS_NO_CACHE;
1092 if(fuAttrFlags & FILE_FLAG_RANDOM_ACCESS_W) openMode |= OPEN_FLAGS_RANDOM;
1093 if(fuAttrFlags & FILE_FLAG_SEQUENTIAL_SCAN_W) openMode |= OPEN_FLAGS_SEQUENTIAL;
1094 // TODO: FILE_FLAG_BACKUP_SEMANTICS_W
1095 // FILE_FLAG_POSIX_SEMANTICS_W are not supported
1096
1097 //TODO: FILE_SHARE_DELETE
1098 if((fuShare & (FILE_SHARE_READ_W | FILE_SHARE_WRITE_W)) == 0 )
1099 openMode |= OPEN_SHARE_DENYREADWRITE;
1100 else
1101 if((fuShare & (FILE_SHARE_READ_W | FILE_SHARE_WRITE_W)) == (FILE_SHARE_READ_W | FILE_SHARE_WRITE_W))
1102 openMode |= OPEN_SHARE_DENYNONE;
1103 else
1104 if(fuShare & FILE_SHARE_READ_W)
1105 openMode |= OPEN_SHARE_DENYWRITE;
1106 else
1107 if(fuShare & FILE_SHARE_WRITE_W)
1108 openMode |= OPEN_SHARE_DENYREAD;
1109
1110 if(fuAccess == (GENERIC_READ_W | GENERIC_WRITE_W))
1111 openMode |= OPEN_ACCESS_READWRITE;
1112 else
1113 if(fuAccess & GENERIC_READ_W)
1114 openMode |= OPEN_ACCESS_READONLY;
1115 else
1116 //mgp: There seems to be a problem where OPEN_ACCESS_WRITEONLY gives an
1117 // Access Error (0x05) if the file is opened with
1118 // OPEN_ACTION_OPEN_IF_EXISTS. So, in that case, change it to
1119 // OPEN_ACCESS_READWRITE
1120 if(fuAccess & GENERIC_WRITE_W)
1121 if (openFlag & OPEN_ACTION_OPEN_IF_EXISTS)
1122 openMode |= OPEN_ACCESS_READWRITE;
1123 else
1124 openMode |= OPEN_ACCESS_WRITEONLY;
1125
1126#if 0
1127 //SvL: Not true; verified in NT! (also messed up access of files on
1128 // readonly volumes)
1129 // CreateFile with OPEN_ALWAYS & GENERIC_READ on non-existing file
1130 // -> creates 0 size file, WriteFile is not allowed
1131 // Same in OS/2.
1132 /* if creating a file, access cannot be readonly! */
1133 if (openFlag & OPEN_ACTION_CREATE_IF_NEW &&
1134 (!(openMode & OPEN_ACCESS_READWRITE) &&
1135 !(openMode & OPEN_ACCESS_WRITEONLY))) {
1136 openMode |= OPEN_ACCESS_READWRITE;
1137 }
1138#endif
1139
1140 if(strlen(lpszFile) == 2 && lpszFile[1] == ':') {
1141 //app tries to open logical volume/partition
1142 openMode |= OPEN_FLAGS_DASD;
1143 }
1144 int retry = 0;
1145 while (retry < 3)
1146 {
1147 dprintf(("DosOpen %s openFlag=%x openMode=%x", lpszFile, openFlag, openMode));
1148 rc = OdinDosOpenL((PSZ)lpszFile,
1149 &hFile,
1150 &actionTaken,
1151 fileSize,
1152 fileAttr,
1153 openFlag,
1154 openMode,
1155 NULL);
1156 if (rc == ERROR_TOO_MANY_OPEN_FILES)
1157 {
1158 ULONG CurMaxFH;
1159 LONG ReqCount = 32;
1160
1161 rc = DosSetRelMaxFH(&ReqCount, &CurMaxFH);
1162 if(rc) {
1163 dprintf(("DosSetRelMaxFH returned %d", rc));
1164 SetLastError(ERROR_TOO_MANY_OPEN_FILES_W);
1165 return INVALID_HANDLE_VALUE_W;
1166 }
1167 dprintf(("DosOpen failed -> increased nr open files to %d", CurMaxFH));
1168 }
1169 #if 0
1170 else if (rc == ERROR_ACCESS_DENIED && (openFlag & OPEN_ACTION_REPLACE_IF_EXISTS))
1171 { /* kso: I have great problems with the REPLACE not working
1172 * So, I guess this emulation may help...
1173 * This problem exist on WS4eB SMP FP1 and Warp4 FP14/Kernel 14059 at least.
1174 */
1175 rc = DosOpen((PSZ)lOemFile,
1176 &hFile,
1177 &actionTaken,
1178 fileSize,
1179 fileAttr,
1180 (openFlag & ~OPEN_ACTION_REPLACE_IF_EXISTS) | OPEN_ACTION_OPEN_IF_EXISTS,
1181 openMode,
1182 NULL);
1183 if (rc == NO_ERROR)
1184 {
1185 rc = DosSetFileSize(hFile, 0);
1186 if (!rc && fileSize > 0)
1187 rc = DosSetFileSize(hFile, fileSize);
1188 if (rc)
1189 {
1190 DosClose(hFile);
1191 hFile = NULLHANDLE;
1192
1193 if (rc != ERROR_TOO_MANY_OPEN_FILES)
1194 break;
1195 }
1196 else break;
1197 }
1198 }
1199 #endif
1200 else break;
1201 retry++;
1202 }
1203
1204 if(rc)
1205 {
1206 // @@@AH 2001-06-02 Win2k SP2 returns error 2 in this case
1207 int winError = error2WinError(rc);
1208 if (winError == ERROR_OPEN_FAILED_W)
1209 winError = ERROR_FILE_NOT_FOUND_W;
1210 SetLastError(winError);
1211 return INVALID_HANDLE_VALUE_W;
1212 }
1213 SetLastError(ERROR_SUCCESS_W);
1214 return hFile;
1215}
1216//******************************************************************************
1217//******************************************************************************
1218DWORD OSLibDosOpenFile(CHAR *lpszFile, UINT fuMode)
1219{
1220 ULONG actionTaken = 0;
1221 LONGLONG fileSize = {0};
1222 ULONG fileAttr = FILE_NORMAL;
1223 ULONG openFlag = 0;
1224 ULONG openMode = 0;
1225 APIRET rc = ERROR_NOT_ENOUGH_MEMORY;
1226 HFILE hFile;
1227
1228 if(!(fuMode & (OF_CREATE_W | OF_READWRITE_W | OF_WRITE_W)))
1229 {
1230 openMode |= OPEN_ACCESS_READONLY;
1231 openFlag |= OPEN_ACTION_OPEN_IF_EXISTS;
1232 }
1233 else
1234 {
1235 if(fuMode & OF_CREATE_W) {
1236 openFlag |= OPEN_ACTION_CREATE_IF_NEW |
1237 OPEN_ACTION_REPLACE_IF_EXISTS;
1238 }
1239 else openFlag |= OPEN_ACTION_OPEN_IF_EXISTS;
1240
1241 if(fuMode & OF_READWRITE_W)
1242 openMode |= OPEN_ACCESS_READWRITE;
1243 else
1244 if(fuMode & OF_WRITE_W)
1245 openMode |= OPEN_ACCESS_WRITEONLY;
1246 else
1247 if(fuMode & OF_CREATE_W)
1248 openMode |= OPEN_ACCESS_READWRITE;
1249 }
1250
1251 if((fuMode & OF_SHARE_DENY_WRITE_W) ||
1252 !(fuMode & (OF_SHARE_DENY_READ_W | OF_SHARE_DENY_NONE_W | OF_SHARE_EXCLUSIVE_W)))
1253 openMode |= OPEN_SHARE_DENYWRITE;
1254 else
1255 if (fuMode & OF_SHARE_DENY_NONE_W)
1256 openMode |= OPEN_SHARE_DENYNONE;
1257 else
1258 if (fuMode & OF_SHARE_DENY_READ_W)
1259 openMode |= OPEN_SHARE_DENYREAD;
1260 else
1261 if (fuMode & OF_SHARE_EXCLUSIVE_W)
1262 openMode |= OPEN_SHARE_DENYREADWRITE;
1263
1264 rc = OdinDosOpenL((PSZ)lpszFile,
1265 &hFile,
1266 &actionTaken,
1267 fileSize,
1268 fileAttr,
1269 openFlag,
1270 openMode,
1271 NULL);
1272
1273 if(rc != NO_ERROR)
1274 {
1275 if(fuMode & OF_EXIST_W)
1276 {
1277 if(rc == ERROR_OPEN_FAILED || rc == ERROR_FILE_NOT_FOUND)
1278 {
1279 SetLastError(ERROR_FILE_NOT_FOUND_W);
1280 return HFILE_ERROR_W;
1281 }
1282 }
1283 if((rc == ERROR_OPEN_FAILED) && (openFlag & OPEN_ACTION_OPEN_IF_EXISTS))
1284 {
1285 SetLastError(ERROR_FILE_NOT_FOUND_W);
1286 }
1287 else SetLastError(error2WinError(rc));
1288
1289 return HFILE_ERROR_W;
1290 }
1291 SetLastError(ERROR_SUCCESS_W);
1292 return hFile;
1293}
1294//******************************************************************************
1295//******************************************************************************
1296BOOL OSLibDosLockFile(DWORD hFile, DWORD dwFlags,
1297 DWORD OffsetLow, DWORD OffsetHigh,
1298 DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh,
1299 LPOVERLAPPED lpOverlapped)
1300{
1301 APIRET rc;
1302
1303 // Set 5 secs timeout for locking file and no other can access this
1304 // file region
1305
1306 if(lpOverlapped) {//TODO:
1307 dprintf(("OSLibDosLockFile: overlapped lock not yet implemented!!"));
1308 }
1309 //TODO: Locking region crossing end of file is permitted. Works in OS/2??
1310 if(f64BitIO)
1311 {
1312 FILELOCKL lockRangeL;
1313
1314 lockRangeL.lOffset.ulLo = OffsetLow;
1315 lockRangeL.lOffset.ulHi = OffsetHigh;
1316 lockRangeL.lRange.ulLo = nNumberOfBytesToLockLow;
1317 lockRangeL.lRange.ulHi = nNumberOfBytesToLockHigh;
1318
1319 rc = OdinDosSetFileLocksL(hFile, NULL, &lockRangeL,
1320 (dwFlags & LOCKFILE_FAIL_IMMEDIATELY_W) ? 0 : 5000, 0);
1321 //SvL: 64 bits values are only supported by JFS
1322 // Try the 32 bits DosSetFileLocks if it fails
1323 // (TODO: should check the partition type instead)
1324 if(rc == ERROR_INVALID_PARAMETER && (OffsetHigh || nNumberOfBytesToLockHigh)) {
1325 goto oldlock;
1326 }
1327 }
1328 else
1329 {
1330oldlock:
1331 FILELOCK lockRange = { OffsetLow, nNumberOfBytesToLockLow };
1332
1333 rc = DosSetFileLocks(hFile, NULL, &lockRange,
1334 (dwFlags & LOCKFILE_FAIL_IMMEDIATELY_W) ? 0 : 5000, 0);
1335 }
1336 if(rc) {
1337 SetLastError(error2WinError(rc));
1338 return FALSE;
1339 }
1340 SetLastError(ERROR_SUCCESS_W);
1341 return TRUE;
1342}
1343//******************************************************************************
1344//******************************************************************************
1345BOOL OSLibDosUnlockFile(DWORD hFile, DWORD OffsetLow, DWORD OffsetHigh,
1346 DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh,
1347 LPOVERLAPPED lpOverlapped)
1348{
1349 APIRET rc;
1350
1351 // Set 5 secs timeout for unlocking file and no other can access this
1352 // file region
1353
1354 if(lpOverlapped) {//TODO:
1355 dprintf(("OSLibDosUnlockFile: overlapped unlock not yet implemented!!"));
1356 }
1357 if(f64BitIO)
1358 {
1359 FILELOCKL unlockRangeL;
1360
1361 unlockRangeL.lOffset.ulLo = OffsetLow;
1362 unlockRangeL.lOffset.ulHi = OffsetHigh;
1363 unlockRangeL.lRange.ulLo = nNumberOfBytesToLockLow;
1364 unlockRangeL.lRange.ulHi = nNumberOfBytesToLockHigh;
1365
1366 rc = OdinDosSetFileLocksL(hFile, &unlockRangeL, NULL, 5000, 0);
1367 //SvL: 64 bits values are only supported by JFS
1368 // Try the 32 bits DosSetFileLocks if it fails
1369 // (TODO: should check the partition type instead)
1370 if(rc == ERROR_INVALID_PARAMETER && (OffsetHigh || nNumberOfBytesToLockHigh)) {
1371 goto oldlock;
1372 }
1373 }
1374 else
1375 {
1376oldlock:
1377 FILELOCK unlockRange = { OffsetLow, nNumberOfBytesToLockLow };
1378
1379 rc = DosSetFileLocks(hFile, &unlockRange, NULL, 5000, 0);
1380 }
1381 if(rc) {
1382 SetLastError(error2WinError(rc));
1383 return FALSE;
1384 }
1385 SetLastError(ERROR_SUCCESS_W);
1386 return TRUE;
1387}
1388//******************************************************************************
1389//******************************************************************************
1390BOOL OSLibDosFlushFileBuffers(DWORD hFile)
1391{
1392 APIRET rc;
1393
1394 rc = DosResetBuffer(hFile);
1395 SetLastError(error2WinError(rc));
1396 return (rc == NO_ERROR);
1397}
1398//******************************************************************************
1399//******************************************************************************
1400DWORD OSLibDosGetFileSize(DWORD hFile, LPDWORD lpdwFileSizeHigh)
1401{
1402 APIRET rc;
1403 ULONG sizeLow;
1404
1405 if(f64BitIO)
1406 {
1407 FILESTATUS3L fsts3ConfigInfoL = {{0}};
1408 ULONG ulBufSize = sizeof(FILESTATUS3L);
1409
1410 rc = DosQueryFileInfo(hFile, FIL_STANDARDL, &fsts3ConfigInfoL, ulBufSize);
1411 if(lpdwFileSizeHigh) {
1412 *lpdwFileSizeHigh = fsts3ConfigInfoL.cbFile.ulHi;
1413 }
1414 sizeLow = fsts3ConfigInfoL.cbFile.ulLo;
1415 }
1416 else
1417 {
1418 FILESTATUS3 fsts3ConfigInfo = {{0}};
1419 ULONG ulBufSize = sizeof(FILESTATUS3);
1420
1421 if(lpdwFileSizeHigh) {
1422 *lpdwFileSizeHigh = 0;
1423 }
1424 rc = DosQueryFileInfo(hFile, FIL_STANDARD, &fsts3ConfigInfo, ulBufSize);
1425 sizeLow = fsts3ConfigInfo.cbFile;
1426 }
1427 if(rc) {
1428 SetLastError(error2WinError(rc));
1429 return -1;
1430 }
1431 SetLastError(ERROR_SUCCESS_W);
1432 return sizeLow;
1433}
1434//******************************************************************************
1435//******************************************************************************
1436DWORD OSLibDosSetFilePointer(DWORD hFile, DWORD OffsetLow, DWORD *OffsetHigh, DWORD method)
1437{
1438 LONGLONG offsetL;
1439 LONGLONG newoffsetL;
1440 APIRET rc;
1441 DWORD newoffset;
1442
1443 switch(method)
1444 {
1445 case FILE_BEGIN_W:
1446 method = FILE_BEGIN;
1447 break;
1448
1449 case FILE_CURRENT_W:
1450 method = FILE_CURRENT;
1451 break;
1452
1453 case FILE_END_W:
1454 method = FILE_END;
1455 break;
1456 }
1457
1458 // PH Note: for a negative 32-bit seek, the OS/2 64-bit version
1459 // needs to be skipped.
1460 if( (f64BitIO) && (OffsetHigh) )
1461 {
1462 offsetL.ulLo = OffsetLow;
1463 offsetL.ulHi = (OffsetHigh) ? *OffsetHigh : 0;
1464 rc = OdinDosSetFilePtrL(hFile, offsetL, method, &newoffsetL);
1465 if(OffsetHigh) {
1466 *OffsetHigh = newoffsetL.ulHi;
1467 }
1468 newoffset = newoffsetL.ulLo;
1469 }
1470 else rc = DosSetFilePtr(hFile, OffsetLow, method, &newoffset);
1471
1472 if(rc)
1473 {
1474 SetLastError(error2WinError(rc));
1475 return -1;
1476 }
1477 SetLastError(ERROR_SUCCESS_W);
1478 return newoffset;
1479}
1480//******************************************************************************
1481//******************************************************************************
1482BOOL OSLibDosSetEndOfFile(DWORD hFile)
1483{
1484 ULONG newFilePos;
1485 LONGLONG FilePosL = {0,0};
1486 LONGLONG newFilePosL;
1487 APIRET rc;
1488
1489 if(f64BitIO) {
1490 rc = OdinDosSetFilePtrL(hFile, FilePosL, FILE_CURRENT, &newFilePosL);
1491 if(rc == 0) {
1492 rc = OdinDosSetFileSizeL(hFile, newFilePosL);
1493 }
1494 }
1495 else {
1496 rc = DosSetFilePtr(hFile, 0, FILE_CURRENT, &newFilePos);
1497 if(rc == 0) {
1498 rc = DosSetFileSize(hFile, newFilePos);
1499 }
1500 }
1501 if(rc) {
1502 SetLastError(error2WinError(rc));
1503 return FALSE;
1504 }
1505 SetLastError(ERROR_SUCCESS_W);
1506 return TRUE;
1507}
1508//******************************************************************************
1509//******************************************************************************
1510BOOL OSLibDosGetFileInformationByHandle(DWORD hFile, BY_HANDLE_FILE_INFORMATION* pInfo)
1511{
1512 APIRET rc;
1513
1514 if(f64BitIO)
1515 {
1516 FILESTATUS4L statusL = { 0 };
1517
1518 rc = DosQueryFileInfo(hFile, FIL_QUERYEASIZEL,
1519 &statusL, sizeof(statusL));
1520 if(rc == NO_ERROR)
1521 {
1522 pInfo->dwFileAttributes = 0;
1523 if(!(statusL.attrFile & NOT_NORMAL))
1524 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_NORMAL_W;
1525 if(statusL.attrFile & FILE_READONLY)
1526 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_READONLY_W;
1527 if(statusL.attrFile & FILE_HIDDEN)
1528 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN_W;
1529 if(statusL.attrFile & FILE_SYSTEM)
1530 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_SYSTEM_W;
1531 if(statusL.attrFile & FILE_DIRECTORY)
1532 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY_W;
1533 if(statusL.attrFile & FILE_ARCHIVED)
1534 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_ARCHIVE_W;
1535
1536 pmDateTimeToFileTime(&statusL.fdateCreation,
1537 &statusL.ftimeCreation,
1538 &pInfo->ftCreationTime);
1539 pmDateTimeToFileTime(&statusL.fdateLastAccess,
1540 &statusL.ftimeLastAccess,
1541 &pInfo->ftLastAccessTime);
1542 pmDateTimeToFileTime(&statusL.fdateLastWrite,
1543 &statusL.ftimeLastWrite,
1544 &pInfo->ftLastWriteTime);
1545
1546 pInfo->nFileSizeHigh = statusL.cbFile.ulHi;
1547 pInfo->nFileSizeLow = statusL.cbFile.ulLo;
1548 pInfo->dwVolumeSerialNumber = 0; //todo
1549 pInfo->nNumberOfLinks = 1;
1550 pInfo->nFileIndexHigh = 0;
1551 pInfo->nFileIndexLow = 0;
1552 }
1553 }
1554 else
1555 {
1556 FILESTATUS4 status = { 0 };
1557
1558 rc = DosQueryFileInfo(hFile, FIL_QUERYEASIZE, &status,
1559 sizeof(status));
1560 if(rc == NO_ERROR)
1561 {
1562 pInfo->dwFileAttributes = 0;
1563 if(!(status.attrFile & NOT_NORMAL))
1564 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_NORMAL_W;
1565 if(status.attrFile & FILE_READONLY)
1566 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_READONLY_W;
1567 if(status.attrFile & FILE_HIDDEN)
1568 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN_W;
1569 if(status.attrFile & FILE_SYSTEM)
1570 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_SYSTEM_W;
1571 if(status.attrFile & FILE_DIRECTORY)
1572 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY_W;
1573 if(status.attrFile & FILE_ARCHIVED)
1574 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_ARCHIVE_W;
1575
1576 pmDateTimeToFileTime(&status.fdateCreation,
1577 &status.ftimeCreation,
1578 &pInfo->ftCreationTime);
1579 pmDateTimeToFileTime(&status.fdateLastAccess,
1580 &status.ftimeLastAccess,
1581 &pInfo->ftLastAccessTime);
1582 pmDateTimeToFileTime(&status.fdateLastWrite,
1583 &status.ftimeLastWrite,
1584 &pInfo->ftLastWriteTime);
1585
1586 pInfo->nFileSizeHigh = 0;
1587 pInfo->nFileSizeLow = status.cbFile;
1588 pInfo->dwVolumeSerialNumber = 0; //todo
1589 pInfo->nNumberOfLinks = 1;
1590 pInfo->nFileIndexHigh = 0;
1591 pInfo->nFileIndexLow = 0;
1592 }
1593 }
1594 if(rc) {
1595 SetLastError(error2WinError(rc));
1596 return FALSE;
1597 }
1598 SetLastError(ERROR_SUCCESS_W);
1599 return TRUE;
1600}
1601//******************************************************************************
1602//******************************************************************************
1603BOOL OSLibDosSetFileTime(DWORD hFile, WORD creationdate, WORD creationtime,
1604 WORD lastaccessdate, WORD lastaccesstime,
1605 WORD lastwritedate, WORD lastwritetime)
1606{
1607 FILESTATUS3 fileInfo;
1608 APIRET rc;
1609
1610 rc = DosQueryFileInfo(hFile, FIL_STANDARD, &fileInfo, sizeof(fileInfo));
1611
1612 if(rc == NO_ERROR)
1613 {
1614 if(creationdate && creationtime) {
1615 fileInfo.fdateCreation = *(FDATE *)&creationdate;
1616 fileInfo.ftimeCreation = *(FTIME *)&creationtime;
1617 }
1618 if(lastaccessdate && lastaccesstime) {
1619 fileInfo.fdateLastAccess = *(FDATE *)&lastaccessdate;
1620 fileInfo.ftimeLastAccess = *(FTIME *)&lastaccesstime;
1621 }
1622 if(lastwritedate && lastwritetime) {
1623 fileInfo.fdateLastWrite = *(FDATE *)&lastwritedate;
1624 fileInfo.ftimeLastWrite = *(FTIME *)&lastwritetime;
1625 }
1626
1627 rc = DosSetFileInfo(hFile, FIL_STANDARD, &fileInfo, sizeof(fileInfo));
1628 }
1629
1630 if(rc)
1631 {
1632 SetLastError(error2WinError(rc));
1633 return FALSE;
1634 }
1635 SetLastError(ERROR_SUCCESS_W);
1636 return TRUE;
1637}
1638//******************************************************************************
1639//******************************************************************************
1640BOOL OSLibDosGetFileTime(DWORD hFile, WORD *creationdate, WORD *creationtime,
1641 WORD *lastaccessdate, WORD *lastaccesstime,
1642 WORD *lastwritedate, WORD *lastwritetime)
1643{
1644 FILESTATUS3 fileInfo;
1645 APIRET rc;
1646
1647 rc = DosQueryFileInfo(hFile, FIL_STANDARD, &fileInfo, sizeof(fileInfo));
1648
1649 if(rc == NO_ERROR)
1650 {
1651 *creationdate = *(WORD *)&fileInfo.fdateCreation;
1652 *creationtime = *(WORD *)&fileInfo.ftimeCreation;
1653 *lastaccessdate = *(WORD *)&fileInfo.fdateLastAccess;
1654 *lastaccesstime = *(WORD *)&fileInfo.ftimeLastAccess;
1655 *lastwritedate = *(WORD *)&fileInfo.fdateLastWrite;
1656 *lastwritetime = *(WORD *)&fileInfo.ftimeLastWrite;
1657 }
1658
1659 if(rc)
1660 {
1661 SetLastError(error2WinError(rc));
1662 return FALSE;
1663 }
1664 SetLastError(ERROR_SUCCESS_W);
1665 return TRUE;
1666}
1667//******************************************************************************
1668//******************************************************************************
1669DWORD OSLibDosSetFilePtr2(DWORD hFile, DWORD offset, DWORD method)
1670{
1671 DWORD newoffset;
1672 APIRET rc;
1673
1674
1675 rc = DosSetFilePtr(hFile, offset, method, &newoffset);
1676 if(rc) {
1677 dprintf(("DosSetFilePtr Error rc:%d", rc));
1678 return -1;
1679 }
1680 else return newoffset;
1681}
1682//******************************************************************************
1683//******************************************************************************
1684DWORD OSLibDosDupHandle(DWORD hFile, DWORD *hNew)
1685{
1686 *hNew = -1;
1687 return DosDupHandle(hFile, hNew);
1688}
1689//******************************************************************************
1690//Returns time spent in kernel & user mode in milliseconds
1691//******************************************************************************
1692BOOL OSLibDosQueryProcTimes(DWORD procid, ULONG *kerneltime, ULONG *usertime)
1693{
1694 APIRET rc;
1695 char *buf;
1696 ULONG size;
1697 ULONG nrthreads = 4;
1698
1699tryagain:
1700 size = sizeof(QTOPLEVEL)+sizeof(QGLOBAL)+sizeof(QPROCESS) + nrthreads*sizeof(QTHREAD);
1701 buf = (char *)malloc(size);
1702 rc = DosQuerySysState(0x1, RESERVED, procid, RESERVED, (PCHAR)buf, size);
1703
1704 if(rc) {
1705 free(buf);
1706 if(rc == ERROR_BUFFER_OVERFLOW) {
1707 nrthreads += 4;
1708 goto tryagain;
1709 }
1710 return FALSE;
1711 }
1712 PQTOPLEVEL top = (PQTOPLEVEL)buf;
1713
1714 *kerneltime = 0;
1715 *usertime = 0;
1716 for(int i=0;i<top->procdata->threadcnt;i++) {
1717 *kerneltime += top->procdata->threads[i].systime;
1718 *usertime += top->procdata->threads[i].usertime;
1719 }
1720 free(buf);
1721 return TRUE;
1722}
1723//******************************************************************************
1724//******************************************************************************
1725// TODO: implement SecurityAttributes parameter
1726DWORD OSLibDosCreateNamedPipe(LPCTSTR lpName,
1727 DWORD dwOpenMode,
1728 DWORD dwPipeMode,
1729 DWORD nMaxInstances,
1730 DWORD nOutBufferSize,
1731 DWORD nInBufferSize,
1732 DWORD nDefaultTimeOut,
1733 LPSECURITY_ATTRIBUTES lpSecurityAttributes)
1734{ DWORD dwOS2Mode = 0;
1735 DWORD dwOS2PipeMode = 0;
1736 LPSTR lpOS2Name;
1737 DWORD hPipe;
1738 DWORD rc, ulAction;
1739
1740 if (dwOpenMode & PIPE_ACCESS_DUPLEX_W)
1741 dwOS2Mode |= NP_ACCESS_DUPLEX;
1742 else
1743 if (dwOpenMode & PIPE_ACCESS_INBOUND_W)
1744 dwOS2Mode |= NP_ACCESS_INBOUND;
1745 else
1746 if (dwOpenMode & PIPE_ACCESS_OUTBOUND_W)
1747 dwOS2Mode |= NP_ACCESS_OUTBOUND;
1748 // TODO:
1749 // if(dwOpenMode & FILE_FLAG_OVERLAPPED)
1750 // if(dwOpenMode & WRITE_DAC)
1751 // if(dwOpenMode & WRITE_OWNER)
1752 // if(dwOpenMode & ACCESS_SYSTEM_SECURITY)
1753 if(dwOpenMode & FILE_FLAG_WRITE_THROUGH_W)
1754 dwOS2Mode |= NP_WRITEBEHIND; // FIXME: I'm not sure!
1755
1756 if (dwPipeMode & PIPE_WAIT_W)
1757 dwOS2PipeMode |= NP_WAIT;
1758 if (dwPipeMode & PIPE_NOWAIT_W)
1759 dwOS2PipeMode |= NP_NOWAIT;
1760 if (dwPipeMode & PIPE_READMODE_BYTE_W)
1761 dwOS2PipeMode |= NP_READMODE_BYTE;
1762 if (dwPipeMode & PIPE_READMODE_MESSAGE_W)
1763 dwOS2PipeMode |= NP_READMODE_MESSAGE;
1764 if (dwPipeMode & PIPE_TYPE_BYTE_W)
1765 dwOS2PipeMode |= NP_TYPE_BYTE;
1766 if (dwPipeMode & PIPE_TYPE_MESSAGE_W)
1767 dwOS2PipeMode |= NP_TYPE_MESSAGE;
1768
1769 if (nMaxInstances>0xff)
1770 {
1771 SetLastError(ERROR_INVALID_PARAMETER_W); // ERROR_INVALID_PARAMETER
1772 return -1; // INVALID_HANDLE_VALUE
1773 }
1774 dwOS2PipeMode |= nMaxInstances;
1775
1776 if (strstr(lpName,"\\\\."))
1777 {
1778 // If pipe is created on the local machine
1779 // we must delete string \\. because
1780 // in Windows named pipes scheme is a \\.\PIPE\pipename
1781 // but in OS/2 only \PIPE\pipename
1782 lpOS2Name = (LPSTR)lpName + 3;
1783 }
1784 else lpOS2Name = (LPSTR)lpName;
1785
1786 dprintf(("DosCreateNPipe(%s,%x,%x,%x,%x,%x)",lpOS2Name,dwOS2Mode,dwOS2PipeMode,nInBufferSize,nOutBufferSize,nDefaultTimeOut));
1787
1788 //if the windows app tries to open another instance of an existing pipe, then
1789 //we must use DosOpen here. So first try DosOpen, if that fails then we can
1790 //create the named pipe
1791 rc = DosOpen(lpOS2Name, &hPipe, &ulAction, 0, FILE_NORMAL, FILE_OPEN,
1792 ((dwOpenMode & PIPE_ACCESS_INBOUND_W) ? OPEN_ACCESS_READWRITE : OPEN_ACCESS_READONLY) |
1793 OPEN_SHARE_DENYNONE, NULL);
1794
1795 if(rc == NO_ERROR) {
1796#if 0
1797 //TODO:
1798 if(dwOpenMode & FILE_FLAG_FIRST_PIPE_INSTANCE_W) {
1799 DosClose(hPipe);
1800 SetLastError(ERROR_ALREADY_EXISTS_W);
1801 return -1;
1802 }
1803 else {
1804#endif
1805 dprintf(("Opening of existing named pipe succeeded"));
1806 SetLastError(ERROR_SUCCESS_W);
1807 return hPipe;
1808// }
1809 }
1810
1811 rc=DosCreateNPipe(lpOS2Name,
1812 &hPipe,
1813 dwOS2Mode,
1814 dwOS2PipeMode,
1815 nInBufferSize,
1816 nInBufferSize,
1817 nDefaultTimeOut); // Timeouts must be tested!
1818
1819 dprintf(("DosCreateNPipe rc=%d",rc));
1820 if (rc)
1821 {
1822 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER_W));
1823 return -1; // INVALID_HANDLE_VALUE
1824 }
1825 SetLastError(ERROR_SUCCESS_W);
1826 return hPipe;
1827}
1828//******************************************************************************
1829//******************************************************************************
1830BOOL OSLibSetNamedPipeState(DWORD hNamedPipe, DWORD dwPipeMode)
1831{
1832 ULONG dwOS2PipeMode = 0;
1833 APIRET rc;
1834
1835 if (dwPipeMode & PIPE_WAIT_W)
1836 dwOS2PipeMode |= NP_WAIT;
1837 if (dwPipeMode & PIPE_NOWAIT_W)
1838 dwOS2PipeMode |= NP_NOWAIT;
1839 if (dwPipeMode & PIPE_READMODE_BYTE_W)
1840 dwOS2PipeMode |= NP_READMODE_BYTE;
1841 if (dwPipeMode & PIPE_READMODE_MESSAGE_W)
1842 dwOS2PipeMode |= NP_READMODE_MESSAGE;
1843
1844 rc = DosSetNPHState(hNamedPipe, dwOS2PipeMode);
1845 if(rc) {
1846 SetLastError(error2WinError(rc, ERROR_INVALID_PARAMETER_W));
1847 return FALSE;
1848 }
1849 SetLastError(ERROR_SUCCESS_W);
1850 return TRUE;
1851}
1852//******************************************************************************
1853//******************************************************************************
1854DWORD OSLibDosOpenPipe(LPCTSTR lpName,
1855 DWORD fuAccess,
1856 DWORD fuShare,
1857 LPSECURITY_ATTRIBUTES lpSecurityAttributes,
1858 DWORD fuCreate,
1859 DWORD fuAttrFlags)
1860{
1861 LPSTR lpOS2Name;
1862 ULONG hPipe;
1863 ULONG rc, ulAction;
1864 ULONG openFlag = 0;
1865 ULONG openMode = 0;
1866
1867
1868 switch(fuCreate)
1869 {
1870 case CREATE_NEW_W:
1871 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_FAIL_IF_EXISTS;
1872 break;
1873 case CREATE_ALWAYS_W:
1874 /* kso 2000-11-26: Not sure if OPEN_ACTION_REPLACE_IF_EXISTS is correct here! It is correct according to
1875 * MSDN, but not according to "The Win32 API SuperBible". Anyway I haven't got time to check it out in
1876 * NT now.
1877 * The problem is that OPEN_ACTION_REPLACE_IF_EXISTS requires write access. It failes with
1878 * rc = ERROR_ACCESS_DENIED (5). Quick fix, use OPEN_IF_EXIST if readonly access.
1879 */
1880 if (fuAccess & GENERIC_WRITE_W)
1881 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS;
1882 else
1883 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
1884 break;
1885 case OPEN_EXISTING_W:
1886 openFlag |= OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
1887 break;
1888 case OPEN_ALWAYS_W:
1889 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
1890 break;
1891 case TRUNCATE_EXISTING_W:
1892 openFlag |= OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS;
1893 break;
1894 }
1895
1896 if(fuAttrFlags & FILE_FLAG_WRITE_THROUGH_W) openMode |= OPEN_FLAGS_WRITE_THROUGH;
1897 if(fuAttrFlags & FILE_FLAG_NO_BUFFERING_W) openMode |= OPEN_FLAGS_NO_CACHE;
1898 if(fuAttrFlags & FILE_FLAG_RANDOM_ACCESS_W) openMode |= OPEN_FLAGS_RANDOM;
1899 if(fuAttrFlags & FILE_FLAG_SEQUENTIAL_SCAN_W) openMode |= OPEN_FLAGS_SEQUENTIAL;
1900 // TODO: FILE_FLAG_BACKUP_SEMANTICS_W
1901 // FILE_FLAG_POSIX_SEMANTICS_W are not supported
1902
1903 //TODO: FILE_SHARE_DELETE
1904 if((fuShare & (FILE_SHARE_READ_W | FILE_SHARE_WRITE_W)) == 0 )
1905 openMode |= OPEN_SHARE_DENYREADWRITE;
1906 else
1907 if((fuShare & (FILE_SHARE_READ_W | FILE_SHARE_WRITE_W)) == (FILE_SHARE_READ_W | FILE_SHARE_WRITE_W))
1908 openMode |= OPEN_SHARE_DENYNONE;
1909 else
1910 if(fuShare & FILE_SHARE_READ_W)
1911 openMode |= OPEN_SHARE_DENYWRITE;
1912 else
1913 if(fuShare & FILE_SHARE_WRITE_W)
1914 openMode |= OPEN_SHARE_DENYREAD;
1915
1916 if(fuAccess == (GENERIC_READ_W | GENERIC_WRITE_W))
1917 openMode |= OPEN_ACCESS_READWRITE;
1918 else
1919 if(fuAccess & GENERIC_READ_W)
1920 openMode |= OPEN_ACCESS_READONLY;
1921 else
1922 if(fuAccess & GENERIC_WRITE_W)
1923 openMode |= OPEN_ACCESS_WRITEONLY;
1924
1925 if (strstr(lpName,"\\\\."))
1926 {
1927 // If pipe is created on the local machine
1928 // we must delete string \\. because
1929 // in Windows named pipes scheme is a \\.\PIPE\pipename
1930 // but in OS/2 only \PIPE\pipename
1931 lpOS2Name = (LPSTR)lpName + 3;
1932 }
1933 else lpOS2Name = (LPSTR)lpName;
1934
1935 rc = DosOpen(lpOS2Name, &hPipe, &ulAction, 0, 0,
1936 openFlag, openMode, NULL);
1937
1938 if(rc == NO_ERROR) {
1939 dprintf(("Opening of existing named pipe succeeded"));
1940 SetLastError(ERROR_SUCCESS_W);
1941 return hPipe;
1942 }
1943
1944 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER_W));
1945 return -1; // INVALID_HANDLE_VALUE
1946}
1947
1948//******************************************************************************
1949//******************************************************************************
1950// TODO: implement lpOverlapped parameter!
1951BOOL OSLibDosConnectNamedPipe(DWORD hNamedPipe, LPOVERLAPPED lpOverlapped)
1952{
1953 DWORD rc;
1954
1955 rc=DosConnectNPipe(hNamedPipe);
1956 dprintf(("DosConnectNPipe rc=%d",rc));
1957
1958 if(rc == NO_ERROR) {
1959 SetLastError(ERROR_SUCCESS_W);
1960 return (TRUE);
1961 }
1962 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1963 return (FALSE);
1964}
1965
1966//******************************************************************************
1967//******************************************************************************
1968BOOL OSLibDosCallNamedPipe( LPCTSTR lpNamedPipeName,
1969 LPVOID lpInBuffer,
1970 DWORD nInBufferSize,
1971 LPVOID lpOutBuffer,
1972 DWORD nOutBufferSize,
1973 LPDWORD lpBytesRead,
1974 DWORD nTimeOut )
1975{
1976 LPSTR lpOS2Name;
1977 DWORD rc;
1978
1979 if (strstr(lpNamedPipeName,"\\\\."))
1980 {
1981 // If pipe is created on the local machine
1982 // we must delete string \\. because
1983 // in Windows named pipes scheme is a \\.\PIPE\pipename
1984 // but in OS/2 only \PIPE\pipename
1985 lpOS2Name = (LPSTR)lpNamedPipeName + 3;
1986 }
1987 else lpOS2Name = (LPSTR)lpNamedPipeName;
1988
1989 rc=DosCallNPipe(lpOS2Name,
1990 lpInBuffer,
1991 nInBufferSize,
1992 lpOutBuffer,
1993 nOutBufferSize,
1994 lpBytesRead,
1995 nTimeOut );
1996
1997
1998 if(rc == NO_ERROR) {
1999 SetLastError(ERROR_SUCCESS_W);
2000 return (TRUE);
2001 }
2002 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
2003 return (FALSE);
2004}
2005
2006//******************************************************************************
2007//******************************************************************************
2008BOOL OSLibDosTransactNamedPipe( DWORD hNamedPipe,
2009 LPVOID lpInBuffer,
2010 DWORD nInBufferSize,
2011 LPVOID lpOutBuffer,
2012 DWORD nOutBufferSize,
2013 LPDWORD lpBytesRead,
2014 LPOVERLAPPED lpOverlapped)
2015{
2016 DWORD rc;
2017
2018 rc=DosTransactNPipe(hNamedPipe,
2019 lpOutBuffer,
2020 nOutBufferSize,
2021 lpInBuffer,
2022 nInBufferSize,
2023 lpBytesRead);
2024
2025 dprintf(("DosTransactNPipe returned rc=%d");)
2026 if(rc == NO_ERROR) {
2027 SetLastError(ERROR_SUCCESS_W);
2028 return (TRUE);
2029 }
2030 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
2031 return (FALSE);
2032}
2033
2034//******************************************************************************
2035//******************************************************************************
2036BOOL OSLibDosPeekNamedPipe(DWORD hPipe,
2037 LPVOID lpvBuffer,
2038 DWORD cbBuffer,
2039 LPDWORD lpcbRead,
2040 LPDWORD lpcbAvail,
2041 LPDWORD lpcbMessage)
2042{
2043 DWORD rc;
2044 AVAILDATA availData ={0};
2045 ULONG ulDummy;
2046
2047 rc=DosPeekNPipe(hPipe,lpvBuffer,cbBuffer,lpcbRead,&availData,&ulDummy);
2048
2049 dprintf(("DosPeekNPipe returned rc=%d",rc));
2050
2051 if (!rc)
2052 {
2053 *lpcbAvail = availData.cbpipe;
2054 *lpcbMessage = availData.cbmessage;
2055 SetLastError(ERROR_SUCCESS_W);
2056 return (TRUE);
2057 }
2058 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
2059 return (FALSE);
2060}
2061//******************************************************************************
2062//******************************************************************************
2063BOOL OSLibDosDisconnectNamedPipe(DWORD hPipe)
2064{
2065 DWORD rc;
2066
2067 rc=DosDisConnectNPipe(hPipe);
2068
2069 dprintf(("DosDisConnectNPipe returned rc=%d",rc));
2070
2071 if(rc == NO_ERROR) {
2072 SetLastError(ERROR_SUCCESS_W);
2073 return (TRUE);
2074 }
2075 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
2076 return (FALSE);
2077}
2078//******************************************************************************
2079//******************************************************************************
2080BOOL OSLibDosWaitNamedPipe(LPCSTR lpszNamedPipeName,
2081 DWORD dwTimeout)
2082{
2083 LPSTR lpOS2Name;
2084 DWORD rc;
2085
2086 if (strstr(lpszNamedPipeName,"\\\\."))
2087 {
2088 // If pipe is created on the local machine
2089 // we must delete string \\. because
2090 // in Windows named pipes scheme is a \\.\PIPE\pipename
2091 // but in OS/2 only \PIPE\pipename
2092 lpOS2Name = (LPSTR)lpszNamedPipeName + 3;
2093 }
2094 else lpOS2Name = (LPSTR)lpszNamedPipeName;
2095
2096 rc=DosWaitNPipe(lpOS2Name,dwTimeout);
2097
2098 dprintf(("DosWaitNPipe returned rc=%d",rc));
2099
2100 if(rc == NO_ERROR) {
2101 SetLastError(ERROR_SUCCESS_W);
2102 return (TRUE);
2103 }
2104 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
2105
2106 return (FALSE);
2107}
2108//******************************************************************************
2109//******************************************************************************
2110BOOL isRoot(CHAR* name)
2111{
2112 if (name[1] == ':')
2113 {
2114 //local name (x:\)
2115 return (name[2] == 0) || !strchr(&name[3],'\\');
2116 } else if (name[0] == '\\')
2117 {
2118 //UNC name (\\resource\drive\)
2119 CHAR *drive,*dir;
2120
2121 drive = strchr(&name[2],'\\');
2122 if (!drive) return FALSE;
2123 dir = strchr(&drive[1],'\\');
2124 if (!dir) return TRUE;
2125 return !strchr(&dir[1],'\\');
2126 } else return FALSE; //unknown
2127}
2128//******************************************************************************
2129//******************************************************************************
2130inline CHAR system2DOSCharacter(CHAR ch)
2131{
2132 switch(ch)
2133 {
2134 case ' ':
2135 case '.':
2136 case '~':
2137 return '_';
2138
2139 default:
2140 return toupper(ch);
2141 }
2142}
2143
2144// TODO: not finished nor correct!!!!
2145VOID long2ShortName(CHAR* longName, CHAR* shortName)
2146{
2147 // check for uplink / root: "." and ".."
2148 if (longName[0] == '.')
2149 {
2150 // if ((strcmp(longName,".") == 0) || (strcmp(longName,"..") == 0))
2151 if (longName[1] == 0) // "."
2152 {
2153 shortName[0] = '.';
2154 shortName[1] = 0;
2155 return;
2156 }
2157
2158 if (longName[1] == '.' && longName[2] == 0) // ".."
2159 {
2160 shortName[0] = '.';
2161 shortName[1] = '.';
2162 shortName[2] = 0;
2163 return;
2164 }
2165 }
2166 else
2167 // check for empty name
2168 if(longName[0] == 0)
2169 {
2170 shortName[0] = 0;
2171 return;
2172 }
2173
2174 INT x;
2175 CHAR *source = longName;
2176
2177 // Test if longName is 8:3 compliant and simply copy
2178 // the filename.
2179 BOOL flag83 = TRUE;
2180
2181 // verify forbidden characters
2182 for (x = 0;
2183 (x < 8) &&
2184 (flag83 == TRUE);
2185 x++)
2186 {
2187 switch (*source)
2188 {
2189 case '.': // a period will cause the loop to abort!
2190 x=1000;
2191 break;
2192
2193 case '/': case '?':
2194 case '*': case ':':
2195 case '\\': case '"':
2196 case ' ':
2197 flag83 = FALSE;
2198 break;
2199 default:
2200 source++;
2201 break;
2202 }
2203 }
2204
2205 // verify we're on a period now
2206 if (flag83 == TRUE)
2207 if (*source != '.')
2208 flag83 = FALSE;
2209 else source++;
2210
2211 // verify extension
2212 if (flag83 == TRUE)
2213 for (INT y = 0;
2214 (y < 3) && (flag83 == TRUE);
2215 y++)
2216 {
2217 switch (*source)
2218 {
2219 case '/': case '?':
2220 case '*': case ':':
2221 case '\\': case '"':
2222 case ' ': case '.':
2223 flag83 = FALSE;
2224 break;
2225 }
2226 source++;
2227 }
2228
2229 // verify we're at the end of the string now
2230 if (flag83 == TRUE)
2231 if (*source != 0)
2232 flag83 = FALSE;
2233
2234 // OK, done
2235 if (flag83 == TRUE)
2236 {
2237 // we might not alter any character here, since
2238 // an app opening a specific file with an 8:3 "alias",
2239 // would surely fail.
2240 strcpy(shortName, longName);
2241
2242 return; // Done
2243 }
2244
2245
2246 // @@@PH
2247 shortName[0] = 0; // this function is disabled anyway ...
2248 return;
2249
2250 CHAR *dest = shortName;
2251 CHAR *ext = strrchr(longName,'.');
2252
2253 //CB: quick and dirty, real FILE~12.EXT is too slow
2254 //PH: We'd have to count the number of non-8:3-compliant files
2255 // within a directory. Or simpler: the number of files within
2256 // the current directory.
2257
2258 //8 character file name
2259 for (x = 0;x < 8;x++)
2260 {
2261 if ((source == ext) || (source[0] == 0)) break;
2262 dest[0] = system2DOSCharacter(source[0]);
2263 source++;
2264 dest++;
2265 }
2266
2267 if (source[0] == 0)
2268 {
2269 dest[0] = 0;
2270 return;
2271 }
2272
2273 if (source != ext)
2274 {
2275 //longName > 8 characters, insert ~1
2276 shortName[6] = '~';
2277 shortName[7] = '1';
2278 }
2279
2280 if (ext)
2281 {
2282 //add extension, 3 characters
2283 dest[0] = ext[0];
2284 dest++;
2285 ext++;
2286 for (x = 0;x < 3;x++)
2287 {
2288 if (ext[0] == 0) break;
2289 dest[0] = system2DOSCharacter(ext[0]);
2290 ext++;
2291 dest++;
2292 }
2293 }
2294 dest[0] = 0;
2295}
2296//******************************************************************************
2297//******************************************************************************
2298VOID translateFileResults(FILESTATUS3 *pResult,LPWIN32_FIND_DATAA pFind,CHAR* achName)
2299{
2300 CHAR* name;
2301
2302 pFind->dwReserved0 = pFind->dwReserved1 = 0;
2303 pFind->dwFileAttributes = pm2WinFileAttributes(pResult->attrFile);
2304
2305 pmDateTimeToFileTime(&pResult->fdateCreation,&pResult->ftimeCreation,&pFind->ftCreationTime);
2306 pmDateTimeToFileTime(&pResult->fdateLastAccess,&pResult->ftimeLastAccess,&pFind->ftLastAccessTime);
2307 pmDateTimeToFileTime(&pResult->fdateLastWrite,&pResult->ftimeLastWrite,&pFind->ftLastWriteTime);
2308
2309 pFind->nFileSizeHigh = 0; //CB: fixme
2310 pFind->nFileSizeLow = pResult->cbFile;
2311 name = strrchr(achName,'\\');
2312 if (name)
2313 {
2314 name++;
2315// strcpy(pFind->cFileName,name);
2316 OemToCharA( name, pFind->cFileName );
2317 }
2318 else
2319 pFind->cFileName[0] = 0;
2320
2321 long2ShortName(pFind->cFileName,pFind->cAlternateFileName);
2322}
2323
2324
2325VOID translateFindResults(FILEFINDBUF3 *pResult,LPWIN32_FIND_DATAA pFind)
2326{
2327 pFind->dwFileAttributes = pm2WinFileAttributes(pResult->attrFile);
2328 pFind->dwReserved0 = pFind->dwReserved1 = 0;
2329
2330 pmDateTimeToFileTime(&pResult->fdateCreation,&pResult->ftimeCreation,&pFind->ftCreationTime);
2331 pmDateTimeToFileTime(&pResult->fdateLastAccess,&pResult->ftimeLastAccess,&pFind->ftLastAccessTime);
2332 pmDateTimeToFileTime(&pResult->fdateLastWrite,&pResult->ftimeLastWrite,&pFind->ftLastWriteTime);
2333
2334 pFind->nFileSizeHigh = 0; //CB: fixme
2335 pFind->nFileSizeLow = pResult->cbFile;
2336// strcpy(pFind->cFileName,pResult->achName);
2337 OemToCharA( pResult->achName, pFind->cFileName );
2338 long2ShortName(pFind->cFileName,pFind->cAlternateFileName);
2339}
2340//******************************************************************************
2341//******************************************************************************
2342DWORD OSLibDosFindFirst(LPCSTR lpFileName,WIN32_FIND_DATAA* lpFindFileData)
2343{
2344 HDIR hDir = -1;
2345 ULONG attrs;
2346 FILEFINDBUF3 result;
2347 ULONG searchCount = 1;
2348
2349 attrs = FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY | FILE_ARCHIVED;
2350 result.achName[0] = 0;
2351
2352 ULONG oldmode = SetErrorMode(SEM_FAILCRITICALERRORS_W);
2353 char lOemFileName[260];
2354
2355 CharToOemA(lpFileName, lOemFileName);
2356
2357 APIRET rc = DosFindFirst((PSZ)lOemFileName,&hDir,attrs,&result,sizeof(result),&searchCount,FIL_STANDARD);
2358
2359 //check root: skip "." and ".." (HPFS, not on FAT)
2360 //check in OSLibDosFindNext not necessary: "." and ".." are the first two entries
2361 if ((rc == 0) && isRoot((LPSTR)lpFileName))
2362 {
2363 while ((strcmp(result.achName,".") == 0) ||
2364 (strcmp(result.achName,"..") == 0))
2365 {
2366 result.achName[0] = 0;
2367 searchCount = 1;
2368 APIRET rc = DosFindNext(hDir,&result,sizeof(result),&searchCount);
2369 if (rc)
2370 {
2371 DosFindClose(hDir);
2372 SetLastError(error2WinError(rc));
2373
2374 SetErrorMode(oldmode);
2375 return INVALID_HANDLE_VALUE_W;
2376 }
2377 }
2378 }
2379
2380 // enable i/o kernel exceptions again
2381 SetErrorMode(oldmode);
2382
2383 if(rc)
2384 {
2385 DosFindClose(hDir);
2386 SetLastError(error2WinError(rc));
2387 return INVALID_HANDLE_VALUE_W;
2388 }
2389 translateFindResults(&result,lpFindFileData);
2390 SetLastError(ERROR_SUCCESS_W);
2391 return hDir;
2392}
2393//******************************************************************************
2394// NOTE: returns "." and ".." in root
2395//******************************************************************************
2396DWORD OSLibDosFindFirstMulti(LPCSTR lpFileName,WIN32_FIND_DATAA *lpFindFileData,DWORD *count)
2397{
2398 HDIR hDir = -1;
2399 ULONG attrs;
2400 FILEFINDBUF3 *result,*data;
2401 ULONG searchCount = *count;
2402
2403 attrs = FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY | FILE_ARCHIVED;
2404 result = (FILEFINDBUF3*)malloc(searchCount*sizeof(FILEFINDBUF3));
2405
2406 ULONG oldmode = SetErrorMode(SEM_FAILCRITICALERRORS_W);
2407 char lOemFileName[260];
2408
2409 CharToOemA(lpFileName, lOemFileName);
2410 APIRET rc = DosFindFirst((PSZ)lOemFileName,&hDir,attrs,result,searchCount*sizeof(FILEFINDBUF3),&searchCount,FIL_STANDARD);
2411 SetErrorMode(oldmode);
2412 if (rc)
2413 {
2414 free(result);
2415 *count = 0;
2416 SetLastError(error2WinError(rc));
2417
2418 return INVALID_HANDLE_VALUE_W;
2419 }
2420
2421 data = result;
2422 for (int x = 0;x < searchCount;x++)
2423 {
2424 translateFindResults(data,&lpFindFileData[x]);
2425 data = (FILEFINDBUF3*)(((DWORD)data)+data->oNextEntryOffset);
2426 }
2427 free(result);
2428 *count = searchCount;
2429
2430 SetLastError(ERROR_SUCCESS_W);
2431 return hDir;
2432}
2433//******************************************************************************
2434//******************************************************************************
2435BOOL OSLibDosFindNext(DWORD hFindFile,WIN32_FIND_DATAA *lpFindFileData)
2436{
2437 FILEFINDBUF3 result;
2438 ULONG searchCount = 1;
2439
2440 APIRET rc = DosFindNext((HDIR)hFindFile,&result,sizeof(result),&searchCount);
2441 if (rc)
2442 {
2443 SetLastError(error2WinError(rc));
2444
2445 return FALSE;
2446 }
2447
2448 translateFindResults(&result,lpFindFileData);
2449 SetLastError(ERROR_SUCCESS_W);
2450 return TRUE;
2451}
2452//******************************************************************************
2453//******************************************************************************
2454BOOL OSLibDosFindNextMulti(DWORD hFindFile,WIN32_FIND_DATAA *lpFindFileData,DWORD *count)
2455{
2456 FILEFINDBUF3 *result,*data;
2457 ULONG searchCount = *count;
2458
2459 result = (FILEFINDBUF3*)malloc(searchCount*sizeof(FILEFINDBUF3));
2460 APIRET rc = DosFindNext((HDIR)hFindFile,result,searchCount*sizeof(FILEFINDBUF3),&searchCount);
2461 if (rc)
2462 {
2463 free(result);
2464 *count = 0;
2465 SetLastError(error2WinError(rc));
2466
2467 return FALSE;
2468 }
2469
2470 data = result;
2471 for (int x = 0;x < searchCount;x++)
2472 {
2473 translateFindResults(data,&lpFindFileData[x]);
2474 data = (FILEFINDBUF3*)(((DWORD)data)+data->oNextEntryOffset);
2475 }
2476 free(result);
2477 *count = searchCount;
2478
2479 SetLastError(ERROR_SUCCESS_W);
2480 return TRUE;
2481}
2482//******************************************************************************
2483//******************************************************************************
2484BOOL OSLibDosFindClose(DWORD hFindFile)
2485{
2486 APIRET rc = DosFindClose((HDIR)hFindFile);
2487 if (rc)
2488 {
2489 SetLastError(error2WinError(rc));
2490 return FALSE;
2491 }
2492
2493 SetLastError(ERROR_SUCCESS_W);
2494 return TRUE;
2495}
2496//******************************************************************************
2497#define FSATTACH_SIZE 256
2498//******************************************************************************
2499DWORD OSLibDosQueryVolumeFS(int drive, LPSTR lpFileSystemNameBuffer, DWORD nFileSystemNameSize)
2500{
2501 PFSQBUFFER2 fsinfo = (PFSQBUFFER2) alloca(FSATTACH_SIZE);
2502 ULONG cb = FSATTACH_SIZE;
2503 char drv[3] = "A:";
2504 char *fsname;
2505 APIRET rc;
2506
2507 if(lpFileSystemNameBuffer == NULL) {
2508 DebugInt3();
2509 return ERROR_INVALID_PARAMETER_W;
2510 }
2511 drv[0] = (char)('A' + drive - 1);
2512
2513 ULONG oldmode = SetErrorMode(SEM_FAILCRITICALERRORS_W);
2514 rc = DosQueryFSAttach(drv, 1, FSAIL_QUERYNAME, fsinfo, &cb);
2515 SetErrorMode(oldmode);
2516
2517 switch(rc) {
2518 case ERROR_INVALID_DRIVE:
2519 return ERROR_INVALID_DRIVE_W;
2520 case ERROR_NO_VOLUME_LABEL:
2521 return ERROR_NO_VOLUME_LABEL_W;
2522 case NO_ERROR:
2523 break;
2524 default:
2525 return ERROR_NOT_ENOUGH_MEMORY; //whatever
2526 }
2527
2528 fsname = (char *)&fsinfo->szName[0] + fsinfo->cbName + 1;
2529
2530 /* @@@PH 2000/08/10 CMD.EXE querys with nFileSystemNameSize == 0
2531 * however does NOT expect to receive an error.
2532 */
2533 strncpy(lpFileSystemNameBuffer,
2534 fsname,
2535 nFileSystemNameSize);
2536 /*
2537 if(strlen(fsname) < nFileSystemNameSize) {
2538 strcpy(lpFileSystemNameBuffer, fsname);
2539 }
2540 else return ERROR_BUFFER_OVERFLOW_W;
2541 */
2542 return ERROR_SUCCESS_W;
2543}
2544//******************************************************************************
2545typedef struct _FSINFOBUF
2546{
2547 ULONG ulVolser; /* Volume serial number */
2548 VOLUMELABEL vol; /* Volume lable */
2549} FSINFOBUF;
2550//******************************************************************************
2551DWORD OSLibDosQueryVolumeSerialAndName(int drive, LPDWORD lpVolumeSerialNumber,
2552 LPSTR lpVolumeNameBuffer, DWORD nVolumeNameSize)
2553{
2554 FSINFOBUF fsi;
2555 APIRET rc;
2556
2557 ULONG oldmode = SetErrorMode(SEM_FAILCRITICALERRORS_W);
2558 rc = DosQueryFSInfo(drive, FSIL_VOLSER, &fsi, sizeof(fsi));
2559 SetErrorMode(oldmode);
2560
2561 switch(rc) {
2562 case ERROR_INVALID_DRIVE:
2563 return ERROR_INVALID_DRIVE_W;
2564 case ERROR_NO_VOLUME_LABEL:
2565 return ERROR_NO_VOLUME_LABEL_W;
2566 case NO_ERROR:
2567 break;
2568 default:
2569 return ERROR_NOT_ENOUGH_MEMORY; //whatever
2570 }
2571
2572 if(lpVolumeSerialNumber) {
2573 *lpVolumeSerialNumber = fsi.ulVolser;
2574 }
2575 if(lpVolumeNameBuffer)
2576 {
2577 if(nVolumeNameSize > fsi.vol.cch) {
2578 strcpy(lpVolumeNameBuffer, (PCHAR)fsi.vol.szVolLabel);
2579 }
2580 else return ERROR_BUFFER_OVERFLOW_W;
2581 }
2582
2583 return ERROR_SUCCESS_W;
2584}
2585//******************************************************************************
2586//******************************************************************************
2587BOOL OSLibGetDiskFreeSpace(LPSTR lpRootPathName, LPDWORD lpSectorsPerCluster,
2588 LPDWORD lpBytesPerSector, LPDWORD lpNumberOfFreeClusters,
2589 LPDWORD lpTotalNumberOfClusters)
2590{
2591 ULONG diskNum;
2592 FSALLOCATE fsAlloc;
2593 APIRET rc;
2594
2595 if(lpRootPathName == 0)
2596 diskNum = 0;
2597 else
2598 if('A' <= *lpRootPathName && *lpRootPathName <= 'Z' )
2599 diskNum = *lpRootPathName - 'A' + 1;
2600 else
2601 if('a' <= *lpRootPathName && *lpRootPathName <= 'z' )
2602 diskNum = *lpRootPathName - 'a' + 1;
2603 else
2604 diskNum = 0;
2605
2606 ULONG oldmode = SetErrorMode(SEM_FAILCRITICALERRORS_W);
2607 rc = DosQueryFSInfo(diskNum, FSIL_ALLOC, &fsAlloc, sizeof(fsAlloc));
2608 SetErrorMode(oldmode);
2609
2610 if(rc == 0)
2611 {
2612 *lpSectorsPerCluster = fsAlloc.cSectorUnit;
2613 *lpBytesPerSector = fsAlloc.cbSector;
2614 *lpNumberOfFreeClusters = fsAlloc.cUnitAvail;
2615 *lpTotalNumberOfClusters = fsAlloc.cUnit;
2616 SetLastError(ERROR_SUCCESS_W);
2617 return TRUE;
2618 }
2619 SetLastError(error2WinError(rc));
2620 return FALSE;
2621}
2622//******************************************************************************
2623//******************************************************************************
2624BOOL OSLibDosGetDiskGeometry(HANDLE hDisk, DWORD cDisk, PVOID pdiskgeom)
2625{
2626 PDISK_GEOMETRY pGeom = (PDISK_GEOMETRY)pdiskgeom;
2627 BYTE param[2] = {0, 0};
2628 ULONG parsize = 2;
2629 BIOSPARAMETERBLOCK bpb;
2630 ULONG datasize = sizeof(bpb);
2631 APIRET rc;
2632
2633 dprintf(("OSLibDosGetDiskGeometry %x %d %x", hDisk, cDisk, pdiskgeom));
2634 param[1] = cDisk - 'A';
2635 rc = DosDevIOCtl((hDisk) ? hDisk : -1, IOCTL_DISK, DSK_GETDEVICEPARAMS, param, 2, &parsize, &bpb, sizeof(bpb), &datasize);
2636 if(rc == 0)
2637 {
2638 pGeom->SectorsPerTrack = bpb.usSectorsPerTrack;
2639 pGeom->BytesPerSector = bpb.usBytesPerSector;
2640 pGeom->TracksPerCylinder = 80; //TODO:!!!!!
2641 pGeom->Cylinders.u.LowPart = bpb.cCylinders;
2642 pGeom->Cylinders.u.HighPart = 0;
2643 switch(bpb.bDeviceType) {
2644 case DEVTYPE_48TPI:
2645 pGeom->MediaType = F5_360_512; //?????
2646 break;
2647 case DEVTYPE_96TPI:
2648 pGeom->MediaType = F5_1Pt2_512; //?????
2649 break;
2650 case DEVTYPE_35:
2651 pGeom->MediaType = F3_720_512;
2652 break;
2653 case DEVTYPE_8SD:
2654 case DEVTYPE_8DD:
2655 pGeom->MediaType = RemovableMedia;
2656 break;
2657 case DEVTYPE_FIXED:
2658 pGeom->MediaType = FixedMedia;
2659 break;
2660 case DEVTYPE_TAPE:
2661 pGeom->MediaType = RemovableMedia;
2662 break;
2663 case DEVTYPE_UNKNOWN: //others, include 1.44 3.5 inch disk drive
2664 pGeom->MediaType = F3_1Pt44_512;
2665 break;
2666 case 8: //RW optical disk
2667 pGeom->MediaType = RemovableMedia;
2668 break;
2669 case 9: //2.88 3.5 inch disk
2670 pGeom->MediaType = F3_2Pt88_512;
2671 break;
2672 }
2673 SetLastError(ERROR_SUCCESS_W);
2674 return TRUE;
2675 }
2676 dprintf(("OSLibDosGetDiskGeometry: error %d -> %d", rc, error2WinError(rc)));
2677 SetLastError(error2WinError(rc));
2678 return FALSE;
2679}
2680//******************************************************************************
2681
2682#define CDType 0x8000
2683#define FloppyType 0x4000
2684#define LanType 0x2000
2685#define LogicalType 0x1000
2686#define VDISKType 0x0800
2687#define OpticalType 0x0400
2688#define NonRemovable 0x01
2689
2690#define FirstDrive 0
2691#define B_Drive_0_Based 1
2692#define Base_1_offset 1
2693#define Binary_to_Printable 0x41
2694#define LastDrive 26
2695#define OpticalSectorsPerCluster 4
2696
2697#define DisketteCylinders 80
2698
2699
2700
2701/**
2702 * Determin the type of a specific drive or the current drive.
2703 *
2704 * @returns DRIVE_UNKNOWN
2705 * DRIVE_NO_ROOT_DIR
2706 * DRIVE_CANNOTDETERMINE
2707 * DRIVE_DOESNOTEXIST
2708 * DRIVE_REMOVABLE
2709 * DRIVE_FIXED
2710 * DRIVE_REMOTE
2711 * DRIVE_CDROM
2712 * DRIVE_RAMDISK
2713 *
2714 * @param ulDrive Index of the drive which type we query.
2715 *
2716 * @status completely implemented and tested
2717 * @author Vitali Pelenyov <sunlover@anduin.net>
2718 * @author bird
2719 */
2720ULONG OSLibGetDriveType(ULONG ulDrive)
2721{
2722 ULONG cbParm;
2723 ULONG cbData;
2724 ULONG ulDriveNum = 0;
2725 ULONG ulDriveMap = 0;
2726 APIRET rc;
2727 ULONG ulDriveType;
2728
2729
2730 /*
2731 * Check if drive is present in the logical drive mask,
2732 */
2733 if ( DosQueryCurrentDisk(&ulDriveNum, &ulDriveMap)
2734 || !(ulDriveMap & (1 << ulDrive))
2735 )
2736 return DRIVE_DOESNOTEXIST_W;
2737
2738
2739 /*
2740 * Optimize floppy queries for A: and B:.
2741 * (These aren't currently a subject of change.)
2742 */
2743 static ULONG ulFloppyMask = 0;
2744 if (ulFloppyMask & (1 << ulDrive))
2745 return DRIVE_REMOVABLE_W;
2746
2747 /*
2748 * Optimize for CDROM requests.
2749 * (These aren't currently a subject of change.)
2750 */
2751 static ULONG ulCDROMMask = 0;
2752 if (ulCDROMMask & (1 << ulDrive))
2753 return DRIVE_CDROM_W;
2754
2755 /*
2756 * Check for CD drives
2757 * We don't have to this everytime. I mean, the os2cdrom.dmd is
2758 * exactly very dynamic when it comes to this info.
2759 */
2760 if (cdDrvLtr.drive_count == 0xffff)
2761 {
2762 HFILE hCDRom2;
2763 ULONG ulAction = 0;
2764
2765 if (DosOpen("\\DEV\\CD-ROM2$", &hCDRom2, &ulAction, 0,
2766 FILE_NORMAL, OPEN_ACTION_OPEN_IF_EXISTS,
2767 OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY, NULL)
2768 == NO_ERROR)
2769 {
2770 cbData = sizeof(cdDrvLtr);
2771 rc = DosDevIOCtl(hCDRom2,
2772 IOC_CDROM_2,
2773 IOCD_RETURN_DRIVE_LETTER,
2774 NULL, 0, NULL,
2775 (PVOID)&cdDrvLtr, sizeof(cdDrvLtr), &cbData);
2776 DosClose(hCDRom2);
2777 }
2778 else
2779 cdDrvLtr.drive_count = 0;
2780 }
2781
2782
2783 /*
2784 * Is the drive present?? Lets the the BPB to check this.
2785 * this should be a pretty speedy call if I'm not much mistaken.
2786 */
2787 BIOSPARAMETERBLOCK bpb = {0};
2788 DSKREQ DskReq;
2789 DskReq.Infotype = 0;
2790 DskReq.DriveUnit = (UCHAR)ulDrive;
2791 cbParm = sizeof(DskReq);
2792 cbData = sizeof(bpb);
2793 if (DosDevIOCtl(-1, IOCTL_DISK, DSK_GETDEVICEPARAMS,
2794 (PVOID)&DskReq, sizeof(DskReq), &cbParm,
2795 (PVOID)&bpb, sizeof(BIOSPARAMETERBLOCK), &cbData)
2796 == NO_ERROR)
2797 {
2798 if (bpb.bDeviceType == 0 && bpb.fsDeviceAttr == 0)
2799 bpb.fsDeviceAttr = LanType; // fix for LAN type drives
2800 }
2801 else
2802 bpb.fsDeviceAttr = LanType; //could be a LAN drive - could it??
2803
2804
2805 /*
2806 * This is a CDROM/DVD drive
2807 *
2808 * Fix: When the cdrom is not last drive letter that
2809 * sometimes reports wrong index, have to check
2810 * that device type can be a CDROM one.
2811 */
2812 if ( cdDrvLtr.drive_count > 0
2813 && (bpb.bDeviceType == DEVTYPE_UNKNOWN || bpb.bDeviceType == DEVTYPE_OPTICAL) // Other or RW optical
2814 && ulDrive >= cdDrvLtr.first_drive_number
2815 && ulDrive < cdDrvLtr.first_drive_number + cdDrvLtr.drive_count
2816 )
2817 bpb.fsDeviceAttr |= CDType;
2818
2819
2820 if (bpb.bDeviceType || bpb.fsDeviceAttr == LanType)
2821 {
2822 if ((bpb.fsDeviceAttr & (CDType | NonRemovable)) == 0)
2823 { // if the device is removable and NOT a CD
2824 CHAR szDevName[4] = "A:";
2825 PFSQBUFFER2 pfsqbuf2;
2826
2827 szDevName[0] += ulDrive;
2828 cbData = sizeof(PFSQBUFFER2) + 3 * CCHMAXPATH;
2829 pfsqbuf2 = (PFSQBUFFER2)malloc(cbData);
2830 DosError(FERR_DISABLEEXCEPTION | FERR_DISABLEHARDERR); // disable error popups
2831 rc = DosQueryFSAttach(&szDevName[0], 0L, FSAIL_QUERYNAME, pfsqbuf2, &cbData);
2832 if (rc == NO_ERROR)
2833 {
2834 if (pfsqbuf2->iType == FSAT_REMOTEDRV)
2835 bpb.fsDeviceAttr |= LanType;
2836 else if (pfsqbuf2->iType == FSAT_LOCALDRV)
2837 {
2838 PSZ pszFSName = (PSZ)pfsqbuf2->szName + pfsqbuf2->cbName + 1;
2839 if (!strcmp(pszFSName, "FAT"))
2840 {
2841 // device is a removable FAT drive, so it MUST be diskette
2842 // as Optical has another name as does LAN and SRVIFS
2843 if (bpb.bSectorsPerCluster != OpticalSectorsPerCluster)
2844 bpb.fsDeviceAttr |= FloppyType;
2845 else
2846 bpb.fsDeviceAttr |= OpticalType;
2847 }
2848 /*
2849 * CDROM detection fix
2850 */
2851 else
2852 {
2853 // device is removable non-FAT, maybe it is CD?
2854 if ( bpb.bDeviceType == DEVTYPE_UNKNOWN
2855 && bpb.bMedia == 5
2856 && bpb.usBytesPerSector > 512
2857 )
2858 bpb.fsDeviceAttr |= CDType;
2859 }
2860 // CDROM detection fix
2861 }
2862 }
2863 else // must be no media or audio only (for CDs at least)
2864 {
2865 if (bpb.cCylinders <= DisketteCylinders) // floppies will always be 80
2866 {
2867 // or less cylinders
2868 if (bpb.bSectorsPerCluster != OpticalSectorsPerCluster)
2869 bpb.fsDeviceAttr |= FloppyType;
2870 else
2871 bpb.fsDeviceAttr |= OpticalType;
2872 }
2873 }
2874
2875 //Enable error popups again
2876 DosError(FERR_ENABLEEXCEPTION | FERR_ENABLEHARDERR);
2877
2878 free(pfsqbuf2);
2879 }
2880 else
2881 {// non removable or CD type. maybe RAM disk
2882 if (!(bpb.fsDeviceAttr & CDType)) // if NOT CD
2883 {
2884 if (bpb.cFATs == 1) // is there only one FAT?
2885 bpb.fsDeviceAttr |= VDISKType; // -> RAM disk
2886 }
2887 }
2888 }
2889
2890
2891 /*
2892 * Determin return value.
2893 */
2894 if (bpb.fsDeviceAttr & FloppyType)
2895 {
2896 ulDriveType = DRIVE_REMOVABLE_W;
2897 /* update floppy cache if A or B */
2898 if (ulDrive <= 1)
2899 ulFloppyMask |= 1 << ulDrive;
2900 }
2901 else if (bpb.fsDeviceAttr & CDType)
2902 {
2903 ulDriveType = DRIVE_CDROM_W;
2904 /* update cdrom cache */
2905 ulCDROMMask |= 1 << ulDrive;
2906 }
2907 else if (bpb.fsDeviceAttr & LanType)
2908 ulDriveType = DRIVE_REMOTE_W;
2909 else if (bpb.fsDeviceAttr & VDISKType)
2910 ulDriveType = DRIVE_RAMDISK_W;
2911 else if (bpb.fsDeviceAttr & OpticalType || bpb.bDeviceType == DEVTYPE_OPTICAL)
2912 ulDriveType = DRIVE_FIXED_W;
2913 else if (bpb.bDeviceType == DEVTYPE_FIXED)
2914 ulDriveType = DRIVE_FIXED_W;
2915 else
2916 ulDriveType = DRIVE_UNKNOWN_W;
2917
2918 return ulDriveType;
2919}
2920//******************************************************************************
2921//Returns bit map where with the mapping of the logical drives
2922//******************************************************************************
2923ULONG OSLibGetLogicalDrives()
2924{
2925 ULONG ulDriveNum = 0; /* Drive number (A=1, B=2, C=3, ...) */
2926 ULONG ulDriveMap = 0; /* Mapping of valid drives */
2927 APIRET rc;
2928
2929 rc = DosQueryCurrentDisk(&ulDriveNum, &ulDriveMap);
2930 if(rc) {
2931 DebugInt3();
2932 SetLastError(error2WinError(rc));
2933 return 0;
2934 }
2935 return ulDriveMap;
2936}
2937//******************************************************************************
2938//******************************************************************************
2939ULONG OSLibDosQueryCurrentDisk()
2940
2941{
2942 ULONG ulDriveNum = 0; /* Drive number (A=1, B=2, C=3, ...) */
2943 ULONG ulDriveMap = 0; /* Mapping of valid drives */
2944 APIRET rc;
2945
2946 rc = DosQueryCurrentDisk(&ulDriveNum, &ulDriveMap);
2947 if(rc) {
2948 DebugInt3();
2949 SetLastError(error2WinError(rc));
2950 return 0;
2951 }
2952 return ulDriveNum;
2953}
2954//******************************************************************************
2955//******************************************************************************
2956BOOL OSLibDosCreatePipe(PHANDLE phfRead,
2957 PHANDLE phfWrite,
2958 LPSECURITY_ATTRIBUTES lpsa,
2959 DWORD dwSize)
2960{
2961 APIRET rc;
2962
2963 dprintf(("DosCreatePipe(%08xh,%08xh,%08xh)\n",
2964 phfRead,
2965 phfWrite,
2966 dwSize));
2967
2968 // select default buffer size
2969 if (dwSize == 0)
2970 dwSize = 4096;
2971
2972 rc = DosCreatePipe(phfRead,
2973 phfWrite,
2974 dwSize);
2975 dprintf(("DosCreatePipe rc=%d",rc));
2976 if (rc)
2977 {
2978 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER_W));
2979 return -1; // INVALID_HANDLE_VALUE
2980 }
2981 SetLastError(ERROR_SUCCESS_W);
2982 return NO_ERROR;
2983}
2984//******************************************************************************
2985//******************************************************************************
2986DWORD SYSTEM OSLibDosDevIOCtl( DWORD hFile, DWORD dwCat, DWORD dwFunc,
2987 PVOID pParm, DWORD dwParmMaxLen, DWORD *pdwParmLen,
2988 PVOID pData, DWORD dwDataMaxLen, DWORD *pdwDataLen)
2989{
2990 APIRET rc;
2991 PVOID pTiledParm = pParm;
2992 BOOL flagTiledParm = FALSE;
2993 PVOID pTiledData = pData;
2994 BOOL flagTiledData = FALSE;
2995
2996#if 1
2997 /*
2998 * Quick and Dirty Fix!
2999 * TO BE REMOVED!
3000 *
3001 * On some VPC installation without CDROM we seem to
3002 * use a concidrable amount of time during Win2k shutdown.
3003 * No idea why, but it has to do with CDROM we think.
3004 *
3005 * So, let's just fail all IOCtls to CD01 if there aren't any
3006 * CDROMs in the system.
3007 *
3008 */
3009
3010 /*
3011 * Check for CD drives
3012 * We don't have to this everytime. I mean, the os2cdrom.dmd is
3013 * exactly very dynamic when it comes to this info.
3014 */
3015 if (cdDrvLtr.drive_count == 0xffff)
3016 {
3017 HFILE hCDRom2;
3018 ULONG ulAction = 0;
3019
3020 if (DosOpen("\\DEV\\CD-ROM2$", &hCDRom2, &ulAction, 0,
3021 FILE_NORMAL, OPEN_ACTION_OPEN_IF_EXISTS,
3022 OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY, NULL)
3023 == NO_ERROR)
3024 {
3025 ULONG cbData = sizeof(cdDrvLtr);
3026 rc = DosDevIOCtl(hCDRom2,
3027 IOC_CDROM_2,
3028 IOCD_RETURN_DRIVE_LETTER,
3029 NULL, 0, NULL,
3030 (PVOID)&cdDrvLtr, sizeof(cdDrvLtr), &cbData);
3031 DosClose(hCDRom2);
3032 }
3033 else
3034 cdDrvLtr.drive_count = 0;
3035 }
3036
3037 if ( cdDrvLtr.drive_count == 0
3038 && (dwCat == IOCTL_CDROMDISK
3039 || (dwCat == IOCTL_CDROMAUDIO
3040 && dwParmMaxLen >= 4 && strncmp((char*)pParm, "CD01", 4))
3041 )
3042 )
3043 {
3044 /* just return some error code */
3045 return ERROR_BAD_COMMAND;
3046 }
3047
3048#endif
3049
3050#define MEM_TILED_CEILING 0x1fffffff
3051
3052 // bounce buffer support
3053 // make sure no parameter or data buffer can pass the tiled memory region
3054 // barrier (usually 512MB). OS/2 kernel does not correctly translate these
3055 // addresses to a 16:16 address used in device driver land. In fact,
3056 // DosDevIOCtl is not a high memory enabled API!
3057
3058 if (pTiledParm && (((DWORD)pTiledParm + max(dwParmMaxLen, *pdwParmLen)) > MEM_TILED_CEILING))
3059 {
3060 rc = DosAllocMem(&pTiledParm, dwParmMaxLen, PAG_READ | PAG_WRITE);
3061 if (rc)
3062 goto _exit_ioctl;
3063
3064 flagTiledParm = TRUE;
3065 }
3066
3067 if (pTiledData && (((DWORD)pTiledData + max(dwDataMaxLen, *pdwDataLen)) > MEM_TILED_CEILING))
3068 {
3069 rc = DosAllocMem(&pTiledData, dwDataMaxLen, PAG_READ | PAG_WRITE);
3070 if (rc)
3071 goto _exit_ioctl;
3072
3073 flagTiledData = TRUE;
3074 }
3075
3076 // copy data from real buffers to
3077 // bounce buffers if necessary
3078 if (pTiledParm != pParm)
3079 memcpy(pTiledParm, pParm, *pdwParmLen);
3080
3081 if (pTiledData != pData)
3082 memcpy(pTiledData, pData, *pdwDataLen);
3083
3084
3085 rc = DosDevIOCtl( (HFILE)hFile, dwCat, dwFunc,
3086 pParm, dwParmMaxLen, pdwParmLen,
3087 pData, dwDataMaxLen, pdwDataLen);
3088
3089 // copy data from bounce buffers to real
3090 // target buffers if necessary
3091 if (pTiledParm != pParm)
3092 memcpy(pParm, pTiledParm, *pdwParmLen);
3093
3094 if (pTiledData != pData)
3095 memcpy(pData, pTiledData, *pdwDataLen);
3096
3097
3098 _exit_ioctl:
3099
3100 // deallocate bounce buffers
3101 if (flagTiledParm)
3102 DosFreeMem(pTiledParm);
3103
3104 if (flagTiledData)
3105 DosFreeMem(pTiledData);
3106
3107 rc = error2WinError(rc, ERROR_INVALID_HANDLE);
3108 SetLastError(rc);
3109 return (DWORD)rc;
3110}
3111
3112/**
3113 * Pure wrapper for DosQueryModulName which returns the OS/2 returncode.
3114 * @returns Returncode from DosQueryModuleName.
3115 * @param hModule Handle of the module which name we query.
3116 * @param cchName Length of the output name buffer.
3117 * @param pszname Pointer to the output name buffer.
3118 * @status Completely implemented.
3119 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
3120 */
3121ULONG OSLibDosQueryModuleName(ULONG hModule, int cchName, char *pszName)
3122{
3123 return DosQueryModuleName(hModule, cchName, pszName);
3124}
3125
3126
3127HINSTANCE OSLibDosLoadModule(LPSTR szModName)
3128{
3129 APIRET rc;
3130 HMODULE hModule = NULLHANDLE;
3131 char name[ CCHMAXPATH ];
3132
3133 rc = DosLoadModule(name, CCHMAXPATH, szModName, &hModule);
3134 if(rc) {
3135 SetLastError(error2WinError(rc,ERROR_FILE_NOT_FOUND));
3136 return 0;
3137 }
3138 SetLastError(ERROR_SUCCESS_W);
3139 return hModule;
3140}
3141//******************************************************************************
3142//******************************************************************************
3143void OSLibDosFreeModule(HINSTANCE hinst)
3144{
3145 DosFreeModule(hinst);
3146}
3147//******************************************************************************
3148//******************************************************************************
3149ULONG OSLibDosQuerySysInfo(ULONG iStart, ULONG iLast, PVOID pBuf, ULONG cbBuf)
3150{
3151 APIRET rc;
3152
3153 rc = DosQuerySysInfo(iStart, iLast, pBuf, cbBuf);
3154 SetLastError(error2WinError(rc,ERROR_INVALID_HANDLE));
3155 return rc;
3156}
3157//******************************************************************************
3158//returned length is number of characters required or used for current dir
3159//*excluding* terminator
3160//******************************************************************************
3161ULONG OSLibDosQueryDir(DWORD length, LPSTR lpszCurDir)
3162{
3163 ULONG drivemap, currentdisk, len;
3164 char *lpszCurDriveAndDir = lpszCurDir +3;
3165 APIRET rc;
3166
3167 len = (length > 3) ? length - 3 : 0;
3168
3169 rc = DosQueryCurrentDir(0, lpszCurDriveAndDir, &len);
3170 if(rc != ERROR_BUFFER_OVERFLOW)
3171 {
3172 if(rc)
3173 {
3174 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER));
3175 return 0;
3176 }
3177 len = strlen(lpszCurDriveAndDir) + 3;
3178
3179 // Dir returned by DosQueryCurDir doesn't include drive, so add it
3180 DosQueryCurrentDisk(&currentdisk, &drivemap);
3181
3182 if(isupper(lpszCurDir[3])) {
3183 lpszCurDir[0] = (char)('A' - 1 + currentdisk);
3184 }
3185 else lpszCurDir[0] = (char)('a' - 1 + currentdisk);
3186
3187 lpszCurDir[1] = ':';
3188 lpszCurDir[2] = '\\';
3189 }
3190 else len += 3; // + 3 since DosQueryCurDir doesn't include drive
3191
3192 SetLastError(ERROR_SUCCESS_W);
3193 return len;
3194}
3195//******************************************************************************
3196//******************************************************************************
3197BOOL OSLibDosBeep(DWORD ulFreq, DWORD ulDuration)
3198{
3199 APIRET rc;
3200
3201 if (ulDuration == -1)
3202 {
3203 SetLastError(ERROR_NOT_SUPPORTED_W);
3204 return FALSE;
3205 }
3206 rc = DosBeep(ulFreq, ulDuration);
3207 SetLastError(error2WinError(rc,ERROR_INVALID_HANDLE));
3208
3209 return (rc == 0);
3210}
3211//******************************************************************************
3212//******************************************************************************
3213ULONG OSLibDosGetModuleFileName(HMODULE hModule, LPTSTR lpszPath, DWORD cchPath)
3214{
3215 PTIB pTIB;
3216 PPIB pPIB;
3217 APIRET rc;
3218
3219 if(hModule == -1 || hModule == 0)
3220 {
3221 DosGetInfoBlocks(&pTIB, &pPIB);
3222 hModule = pPIB->pib_hmte;
3223 }
3224 *lpszPath = 0;
3225 rc = DosQueryModuleName(hModule, cchPath, lpszPath);
3226
3227 DWORD len = strlen(lpszPath);
3228 SetLastError(error2WinError(rc,ERROR_INVALID_HANDLE));
3229 return len;
3230}
3231//******************************************************************************
3232//******************************************************************************
3233ULONG OSLibDosGetProcAddress(HMODULE hModule, LPCSTR lpszProc)
3234{
3235 APIRET rc;
3236 PFN pfn = NULL;
3237 ULONG ordinal = (((ULONG)lpszProc) <= 0xFFFF) ? (ULONG)lpszProc : 0;
3238 HMODULE hmod = (HMODULE)hModule;
3239
3240 rc = DosQueryProcAddr( hmod, ordinal, (PSZ)lpszProc, &pfn );
3241 if(rc == ERROR_INVALID_HANDLE && pfn == NULL) {
3242 CHAR pszError[32], pszModule[CCHMAXPATH];
3243
3244 if(DosQueryModuleName( hmod, CCHMAXPATH, pszModule ) == 0 &&
3245 DosLoadModule( pszError, 32, pszModule, &hmod ) == 0)
3246 {
3247 rc = DosQueryProcAddr(hmod, ordinal, (PSZ)lpszProc, &pfn);
3248 }
3249 }
3250 SetLastError(error2WinError(rc,ERROR_INVALID_HANDLE));
3251
3252 return (ULONG)pfn;
3253}
3254//******************************************************************************
3255//******************************************************************************
3256BOOL OSLibDosSetThreadAffinity(DWORD dwThreadAffinityMask)
3257{
3258 static PROC_DosSetThreadAffinity pfnDosSetThreadAffinity = NULL;
3259 static BOOL fInit = FALSE;
3260 MPAFFINITY mask;
3261 APIRET rc;
3262
3263 if(fInit == FALSE && pfnDosSetThreadAffinity == NULL)
3264 {
3265 ULONG nrCPUs;
3266
3267 rc = DosQuerySysInfo(QSV_NUMPROCESSORS, QSV_NUMPROCESSORS, &nrCPUs, sizeof(nrCPUs));
3268 if (rc != 0 || nrCPUs == 1)
3269 {//not supported
3270 fInit = TRUE;
3271 SetLastError(ERROR_SUCCESS_W);
3272 return TRUE;
3273 }
3274
3275 HMODULE hDoscalls;
3276 if(DosQueryModuleHandle("DOSCALLS", &hDoscalls) == NO_ERROR) {
3277 DosQueryProcAddr(hDoscalls, 564, NULL, (PFN *)&pfnDosSetThreadAffinity);
3278 }
3279 fInit = TRUE;
3280 }
3281 if(fInit && pfnDosSetThreadAffinity == NULL) {
3282 SetLastError(ERROR_SUCCESS_W);
3283 return TRUE;
3284 }
3285 USHORT sel = RestoreOS2FS();
3286
3287 mask.mask[0] = dwThreadAffinityMask;
3288 mask.mask[1] = 0; //TODO: this might not be a good idea, but then again, not many people have > 32 cpus
3289
3290 rc = pfnDosSetThreadAffinity(&mask);
3291 SetFS(sel);
3292
3293 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER));
3294 return (rc == NO_ERROR);
3295}
3296//******************************************************************************
3297//******************************************************************************
3298BOOL OSLibDosQueryAffinity(DWORD fMaskType, DWORD *pdwThreadAffinityMask)
3299{
3300 static PROC_DosQueryThreadAffinity pfnDosQueryThreadAffinity = NULL;
3301 static BOOL fInit = FALSE;
3302 MPAFFINITY mask;
3303 APIRET rc;
3304
3305 if(fInit == FALSE && pfnDosQueryThreadAffinity == NULL)
3306 {
3307 ULONG nrCPUs;
3308
3309 rc = DosQuerySysInfo(QSV_NUMPROCESSORS, QSV_NUMPROCESSORS, &nrCPUs, sizeof(nrCPUs));
3310 if (rc != 0 || nrCPUs == 1)
3311 {//not supported
3312 fInit = TRUE;
3313 *pdwThreadAffinityMask = 1;
3314 SetLastError(ERROR_SUCCESS_W);
3315 return TRUE;
3316 }
3317
3318 HMODULE hDoscalls;
3319 if(DosQueryModuleHandle("DOSCALLS", &hDoscalls) == NO_ERROR) {
3320 DosQueryProcAddr(hDoscalls, 563, NULL, (PFN *)&pfnDosQueryThreadAffinity);
3321 }
3322 fInit = TRUE;
3323 }
3324 if(fInit && pfnDosQueryThreadAffinity == NULL) {
3325 *pdwThreadAffinityMask = 1;
3326 SetLastError(ERROR_SUCCESS_W);
3327 return TRUE;
3328 }
3329
3330 ULONG scope = (fMaskType == MASK_SYSTEM) ? AFNTY_SYSTEM : AFNTY_THREAD;
3331
3332 USHORT sel = RestoreOS2FS();
3333
3334 rc = pfnDosQueryThreadAffinity(scope, &mask);
3335 SetFS(sel);
3336
3337 if(rc == NO_ERROR) {
3338 *pdwThreadAffinityMask = mask.mask[0];
3339 }
3340
3341 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER));
3342 return (rc == NO_ERROR);
3343}
3344//******************************************************************************
3345//******************************************************************************
3346DWORD OSLibDosSetPriority(ULONG tid, int priority)
3347{
3348 DWORD ret, os2priorityclass;
3349 LONG os2prioritydelta;
3350 APIRET rc;
3351
3352 switch(priority)
3353 {
3354 case THREAD_PRIORITY_IDLE_W:
3355 os2priorityclass = PRTYC_IDLETIME;
3356 os2prioritydelta = 0;
3357 break;
3358 case THREAD_PRIORITY_LOWEST_W:
3359 os2priorityclass = PRTYC_REGULAR;
3360 os2prioritydelta = PRTYD_MINIMUM;
3361 break;
3362 case THREAD_PRIORITY_BELOW_NORMAL_W:
3363 os2priorityclass = PRTYC_REGULAR;
3364 os2prioritydelta = -15;
3365 break;
3366 case THREAD_PRIORITY_NORMAL_W:
3367 os2priorityclass = PRTYC_REGULAR;
3368 os2prioritydelta = 0;
3369 break;
3370 case THREAD_PRIORITY_ABOVE_NORMAL_W:
3371 os2priorityclass = PRTYC_REGULAR;
3372 os2prioritydelta = 15;
3373 break;
3374 case THREAD_PRIORITY_HIGHEST_W:
3375 os2priorityclass = PRTYC_REGULAR;
3376 os2prioritydelta = PRTYD_MAXIMUM;
3377 break;
3378 case THREAD_PRIORITY_TIME_CRITICAL_W:
3379 os2priorityclass = PRTYC_TIMECRITICAL;
3380 os2prioritydelta = 0;
3381 break;
3382 default:
3383 dprintf(("!WARNING!: Invalid priority!!"));
3384 SetLastError(ERROR_INVALID_PARAMETER_W);
3385 return ERROR_INVALID_PARAMETER_W;
3386 }
3387 rc = DosSetPriority(PRTYS_THREAD, os2priorityclass, os2prioritydelta, tid);
3388 ret = error2WinError(rc, ERROR_INVALID_PARAMETER);
3389 SetLastError(ret);
3390 return ret;
3391}
3392//******************************************************************************
3393//******************************************************************************
3394void OSLibDosSleep(ULONG msecs)
3395{
3396 DosSleep(msecs);
3397}
3398//******************************************************************************
3399//******************************************************************************
3400void OSLibDosExitThread(ULONG retcode)
3401{
3402 DosExit(EXIT_THREAD, retcode);
3403}
3404//******************************************************************************
3405//******************************************************************************
3406DWORD OSLibDosDevConfig(PVOID pdevinfo,
3407 ULONG item)
3408{
3409 return (DWORD)DosDevConfig(pdevinfo, item);
3410}
3411//******************************************************************************
3412//******************************************************************************
3413DWORD OSLibDosGetNumPhysDrives()
3414{
3415 USHORT usNumDrives = 0; /* Data return buffer */
3416 ULONG ulDataLen = sizeof(USHORT); /* Data return buffer length */
3417 APIRET rc = NO_ERROR; /* Return code */
3418
3419 /* Request a count of the number of partitionable disks in the system */
3420
3421 rc = DosPhysicalDisk(INFO_COUNT_PARTITIONABLE_DISKS,
3422 &usNumDrives,
3423 ulDataLen,
3424 NULL, /* No parameter for this function */
3425 0L);
3426
3427 if (rc != NO_ERROR) {
3428 dprintf(("DosPhysicalDisk error: return code = %u\n", rc));
3429 return 0;
3430 }
3431 else {
3432 dprintf(("DosPhysicalDisk: %u partitionable disk(s)\n",usNumDrives));
3433 }
3434 return usNumDrives;
3435}
3436//******************************************************************************
3437//******************************************************************************
3438
Note: See TracBrowser for help on using the repository browser.