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

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

DT: GetFileTime & SetFileTime fixes; need to convert between UTC and local file time

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