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

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

FindFirstFile: return ERROR_FILE_NOT_FOUND if DosFindFirst returns ERROR_PATH_NOT_FOUND

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