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

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

AH: MoveFile: detect if source and target file names are on a different drive and use DosCopy/DosDelete instead of DosMove in this case

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