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

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

Hot fix for 0 CDROMs. first try!

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