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

Last change on this file since 21302 was 21302, checked in by ydario, 16 years ago

Kernel32 updates.

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