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

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

Rewrote GetFileAttributesA & translate filename used from Windows to OS/2 codepage

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