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

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

hard disk access updates & fixes

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