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

Last change on this file since 10132 was 10132, checked in by sandervl, 22 years ago

CreatePipe: create unique named pipe

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