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

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

moved OS2 memory functions into seperate file

File size: 100.4 KB
Line 
1/* $Id: oslibdos.cpp,v 1.107 2002-07-13 15:58:20 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#define FSATTACH_SIZE 256
2288//******************************************************************************
2289DWORD OSLibDosQueryVolumeFS(int drive, LPSTR lpFileSystemNameBuffer, DWORD nFileSystemNameSize)
2290{
2291 PFSQBUFFER2 fsinfo = (PFSQBUFFER2) alloca(FSATTACH_SIZE);
2292 ULONG cb = FSATTACH_SIZE;
2293 char drv[3] = "A:";
2294 char *fsname;
2295 APIRET rc;
2296
2297 if(lpFileSystemNameBuffer == NULL) {
2298 DebugInt3();
2299 return ERROR_INVALID_PARAMETER_W;
2300 }
2301 drv[0] = (char)('A' + drive - 1);
2302
2303 ULONG oldmode = SetErrorMode(SEM_FAILCRITICALERRORS_W);
2304 rc = DosQueryFSAttach(drv, 1, FSAIL_QUERYNAME, fsinfo, &cb);
2305 SetErrorMode(oldmode);
2306
2307 switch(rc) {
2308 case ERROR_INVALID_DRIVE:
2309 return ERROR_INVALID_DRIVE_W;
2310 case ERROR_NO_VOLUME_LABEL:
2311 return ERROR_NO_VOLUME_LABEL_W;
2312 case NO_ERROR:
2313 break;
2314 default:
2315 return ERROR_NOT_ENOUGH_MEMORY; //whatever
2316 }
2317
2318 fsname = (char *)&fsinfo->szName[0] + fsinfo->cbName + 1;
2319
2320 /* @@@PH 2000/08/10 CMD.EXE querys with nFileSystemNameSize == 0
2321 * however does NOT expect to receive an error.
2322 */
2323 strncpy(lpFileSystemNameBuffer,
2324 fsname,
2325 nFileSystemNameSize);
2326 /*
2327 if(strlen(fsname) < nFileSystemNameSize) {
2328 strcpy(lpFileSystemNameBuffer, fsname);
2329 }
2330 else return ERROR_BUFFER_OVERFLOW_W;
2331 */
2332 return ERROR_SUCCESS_W;
2333}
2334//******************************************************************************
2335typedef struct _FSINFOBUF
2336{
2337 ULONG ulVolser; /* Volume serial number */
2338 VOLUMELABEL vol; /* Volume lable */
2339} FSINFOBUF;
2340//******************************************************************************
2341DWORD OSLibDosQueryVolumeSerialAndName(int drive, LPDWORD lpVolumeSerialNumber,
2342 LPSTR lpVolumeNameBuffer, DWORD nVolumeNameSize)
2343{
2344 FSINFOBUF fsi;
2345 APIRET rc;
2346
2347 ULONG oldmode = SetErrorMode(SEM_FAILCRITICALERRORS_W);
2348 rc = DosQueryFSInfo(drive, FSIL_VOLSER, &fsi, sizeof(fsi));
2349 SetErrorMode(oldmode);
2350
2351 switch(rc) {
2352 case ERROR_INVALID_DRIVE:
2353 return ERROR_INVALID_DRIVE_W;
2354 case ERROR_NO_VOLUME_LABEL:
2355 return ERROR_NO_VOLUME_LABEL_W;
2356 case NO_ERROR:
2357 break;
2358 default:
2359 return ERROR_NOT_ENOUGH_MEMORY; //whatever
2360 }
2361
2362 if(lpVolumeSerialNumber) {
2363 *lpVolumeSerialNumber = fsi.ulVolser;
2364 }
2365 if(lpVolumeNameBuffer)
2366 {
2367 if(nVolumeNameSize > fsi.vol.cch) {
2368 strcpy(lpVolumeNameBuffer, (PCHAR)fsi.vol.szVolLabel);
2369 }
2370 else return ERROR_BUFFER_OVERFLOW_W;
2371 }
2372
2373 return ERROR_SUCCESS_W;
2374}
2375//******************************************************************************
2376//******************************************************************************
2377BOOL OSLibGetDiskFreeSpace(LPSTR lpRootPathName, LPDWORD lpSectorsPerCluster,
2378 LPDWORD lpBytesPerSector, LPDWORD lpNumberOfFreeClusters,
2379 LPDWORD lpTotalNumberOfClusters)
2380{
2381 ULONG diskNum;
2382 FSALLOCATE fsAlloc;
2383 APIRET rc;
2384
2385 if(lpRootPathName == 0)
2386 diskNum = 0;
2387 else
2388 if('A' <= *lpRootPathName && *lpRootPathName <= 'Z' )
2389 diskNum = *lpRootPathName - 'A' + 1;
2390 else
2391 if('a' <= *lpRootPathName && *lpRootPathName <= 'z' )
2392 diskNum = *lpRootPathName - 'a' + 1;
2393 else
2394 diskNum = 0;
2395
2396 ULONG oldmode = SetErrorMode(SEM_FAILCRITICALERRORS_W);
2397 rc = DosQueryFSInfo(diskNum, FSIL_ALLOC, &fsAlloc, sizeof(fsAlloc));
2398 SetErrorMode(oldmode);
2399
2400 if(rc == 0)
2401 {
2402 *lpSectorsPerCluster = fsAlloc.cSectorUnit;
2403 *lpBytesPerSector = fsAlloc.cbSector;
2404 *lpNumberOfFreeClusters = fsAlloc.cUnitAvail;
2405 *lpTotalNumberOfClusters = fsAlloc.cUnit;
2406 SetLastError(ERROR_SUCCESS_W);
2407 return TRUE;
2408 }
2409 SetLastError(error2WinError(rc));
2410 return FALSE;
2411}
2412//******************************************************************************
2413//******************************************************************************
2414BOOL OSLibDosGetDiskGeometry(HANDLE hDisk, DWORD cDisk, PVOID pdiskgeom)
2415{
2416 PDISK_GEOMETRY pGeom = (PDISK_GEOMETRY)pdiskgeom;
2417 BYTE param[2] = {0, 0};
2418 ULONG parsize = 2;
2419 BIOSPARAMETERBLOCK bpb;
2420 ULONG datasize = sizeof(bpb);
2421 APIRET rc;
2422
2423 dprintf(("OSLibDosGetDiskGeometry %x %d %x", hDisk, cDisk, pdiskgeom));
2424 param[1] = cDisk - 'A';
2425 rc = DosDevIOCtl((hDisk) ? hDisk : -1, IOCTL_DISK, DSK_GETDEVICEPARAMS, param, 2, &parsize, &bpb, sizeof(bpb), &datasize);
2426 if(rc == 0)
2427 {
2428 pGeom->SectorsPerTrack = bpb.usSectorsPerTrack;
2429 pGeom->BytesPerSector = bpb.usBytesPerSector;
2430 pGeom->TracksPerCylinder = 80; //TODO:!!!!!
2431 pGeom->Cylinders.u.LowPart = bpb.cCylinders;
2432 pGeom->Cylinders.u.HighPart = 0;
2433 switch(bpb.bDeviceType) {
2434 case DEVTYPE_48TPI:
2435 pGeom->MediaType = F5_360_512; //?????
2436 break;
2437 case DEVTYPE_96TPI:
2438 pGeom->MediaType = F5_1Pt2_512; //?????
2439 break;
2440 case DEVTYPE_35:
2441 pGeom->MediaType = F3_720_512;
2442 break;
2443 case DEVTYPE_8SD:
2444 case DEVTYPE_8DD:
2445 pGeom->MediaType = RemovableMedia;
2446 break;
2447 case DEVTYPE_FIXED:
2448 pGeom->MediaType = FixedMedia;
2449 break;
2450 case DEVTYPE_TAPE:
2451 pGeom->MediaType = RemovableMedia;
2452 break;
2453 case DEVTYPE_UNKNOWN: //others, include 1.44 3.5 inch disk drive
2454 pGeom->MediaType = F3_1Pt44_512;
2455 break;
2456 case 8: //RW optical disk
2457 pGeom->MediaType = RemovableMedia;
2458 break;
2459 case 9: //2.88 3.5 inch disk
2460 pGeom->MediaType = F3_2Pt88_512;
2461 break;
2462 }
2463 SetLastError(ERROR_SUCCESS_W);
2464 return TRUE;
2465 }
2466 dprintf(("OSLibDosGetDiskGeometry: error %d -> %d", rc, error2WinError(rc)));
2467 SetLastError(error2WinError(rc));
2468 return FALSE;
2469}
2470//******************************************************************************
2471
2472#define CDType 0x8000
2473#define FloppyType 0x4000
2474#define LanType 0x2000
2475#define LogicalType 0x1000
2476#define VDISKType 0x0800
2477#define OpticalType 0x0400
2478#define NonRemovable 0x01
2479
2480#define FirstDrive 0
2481#define B_Drive_0_Based 1
2482#define Base_1_offset 1
2483#define Binary_to_Printable 0x41
2484#define LastDrive 26
2485#define OpticalSectorsPerCluster 4
2486
2487#define DisketteCylinders 80
2488
2489
2490
2491/**
2492 * Determin the type of a specific drive or the current drive.
2493 *
2494 * @returns DRIVE_UNKNOWN
2495 * DRIVE_NO_ROOT_DIR
2496 * DRIVE_CANNOTDETERMINE
2497 * DRIVE_DOESNOTEXIST
2498 * DRIVE_REMOVABLE
2499 * DRIVE_FIXED
2500 * DRIVE_REMOTE
2501 * DRIVE_CDROM
2502 * DRIVE_RAMDISK
2503 *
2504 * @param ulDrive Index of the drive which type we query.
2505 *
2506 * @status completely implemented and tested
2507 * @author Vitali Pelenyov <sunlover@anduin.net>
2508 * @author bird
2509 */
2510ULONG OSLibGetDriveType(ULONG ulDrive)
2511{
2512 ULONG cbParm;
2513 ULONG cbData;
2514 ULONG ulDriveNum = 0;
2515 ULONG ulDriveMap = 0;
2516 APIRET rc;
2517 ULONG ulDriveType;
2518
2519
2520 /*
2521 * Check if drive is present in the logical drive mask,
2522 */
2523 if ( DosQueryCurrentDisk(&ulDriveNum, &ulDriveMap)
2524 || !(ulDriveMap & (1 << ulDrive))
2525 )
2526 return DRIVE_DOESNOTEXIST_W;
2527
2528
2529 /*
2530 * Optimize floppy queries for A: and B:.
2531 * (These aren't currently a subject of change.)
2532 */
2533 static ULONG ulFloppyMask = 0;
2534 if (ulFloppyMask & (1 << ulDrive))
2535 return DRIVE_REMOVABLE_W;
2536
2537 /*
2538 * Optimize for CDROM requests.
2539 * (These aren't currently a subject of change.)
2540 */
2541 static ULONG ulCDROMMask = 0;
2542 if (ulCDROMMask & (1 << ulDrive))
2543 return DRIVE_CDROM_W;
2544
2545 /*
2546 * Check for CD drives
2547 * We don't have to this everytime. I mean, the os2cdrom.dmd is
2548 * exactly very dynamic when it comes to this info.
2549 */
2550 if (cdDrvLtr.drive_count == 0xffff)
2551 {
2552 HFILE hCDRom2;
2553 ULONG ulAction = 0;
2554
2555 if (DosOpen("\\DEV\\CD-ROM2$", &hCDRom2, &ulAction, 0,
2556 FILE_NORMAL, OPEN_ACTION_OPEN_IF_EXISTS,
2557 OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY, NULL)
2558 == NO_ERROR)
2559 {
2560 cbData = sizeof(cdDrvLtr);
2561 rc = DosDevIOCtl(hCDRom2,
2562 IOC_CDROM_2,
2563 IOCD_RETURN_DRIVE_LETTER,
2564 NULL, 0, NULL,
2565 (PVOID)&cdDrvLtr, sizeof(cdDrvLtr), &cbData);
2566 DosClose(hCDRom2);
2567 }
2568 else
2569 cdDrvLtr.drive_count = 0;
2570 }
2571
2572
2573 /*
2574 * Is the drive present?? Lets the the BPB to check this.
2575 * this should be a pretty speedy call if I'm not much mistaken.
2576 */
2577 BIOSPARAMETERBLOCK bpb = {0};
2578 DSKREQ DskReq;
2579 DskReq.Infotype = 0;
2580 DskReq.DriveUnit = (UCHAR)ulDrive;
2581 cbParm = sizeof(DskReq);
2582 cbData = sizeof(bpb);
2583 if (DosDevIOCtl(-1, IOCTL_DISK, DSK_GETDEVICEPARAMS,
2584 (PVOID)&DskReq, sizeof(DskReq), &cbParm,
2585 (PVOID)&bpb, sizeof(BIOSPARAMETERBLOCK), &cbData)
2586 == NO_ERROR)
2587 {
2588 if (bpb.bDeviceType == 0 && bpb.fsDeviceAttr == 0)
2589 bpb.fsDeviceAttr = LanType; // fix for LAN type drives
2590 }
2591 else
2592 bpb.fsDeviceAttr = LanType; //could be a LAN drive - could it??
2593
2594
2595 /*
2596 * This is a CDROM/DVD drive
2597 *
2598 * Fix: When the cdrom is not last drive letter that
2599 * sometimes reports wrong index, have to check
2600 * that device type can be a CDROM one.
2601 */
2602 if ( cdDrvLtr.drive_count > 0
2603 && (bpb.bDeviceType == DEVTYPE_UNKNOWN || bpb.bDeviceType == DEVTYPE_OPTICAL) // Other or RW optical
2604 && ulDrive >= cdDrvLtr.first_drive_number
2605 && ulDrive < cdDrvLtr.first_drive_number + cdDrvLtr.drive_count
2606 )
2607 bpb.fsDeviceAttr |= CDType;
2608
2609
2610 if (bpb.bDeviceType || bpb.fsDeviceAttr == LanType)
2611 {
2612 if ((bpb.fsDeviceAttr & (CDType | NonRemovable)) == 0)
2613 { // if the device is removable and NOT a CD
2614 CHAR szDevName[4] = "A:";
2615 PFSQBUFFER2 pfsqbuf2;
2616
2617 szDevName[0] += ulDrive;
2618 cbData = sizeof(PFSQBUFFER2) + 3 * CCHMAXPATH;
2619 pfsqbuf2 = (PFSQBUFFER2)malloc(cbData);
2620 DosError(FERR_DISABLEEXCEPTION | FERR_DISABLEHARDERR); // disable error popups
2621 rc = DosQueryFSAttach(&szDevName[0], 0L, FSAIL_QUERYNAME, pfsqbuf2, &cbData);
2622 if (rc == NO_ERROR)
2623 {
2624 if (pfsqbuf2->iType == FSAT_REMOTEDRV)
2625 bpb.fsDeviceAttr |= LanType;
2626 else if (pfsqbuf2->iType == FSAT_LOCALDRV)
2627 {
2628 PSZ pszFSName = (PSZ)pfsqbuf2->szName + pfsqbuf2->cbName + 1;
2629 if (!strcmp(pszFSName, "FAT"))
2630 {
2631 // device is a removable FAT drive, so it MUST be diskette
2632 // as Optical has another name as does LAN and SRVIFS
2633 if (bpb.bSectorsPerCluster != OpticalSectorsPerCluster)
2634 bpb.fsDeviceAttr |= FloppyType;
2635 else
2636 bpb.fsDeviceAttr |= OpticalType;
2637 }
2638 /*
2639 * CDROM detection fix
2640 */
2641 else
2642 {
2643 // device is removable non-FAT, maybe it is CD?
2644 if ( bpb.bDeviceType == DEVTYPE_UNKNOWN
2645 && bpb.bMedia == 5
2646 && bpb.usBytesPerSector > 512
2647 )
2648 bpb.fsDeviceAttr |= CDType;
2649 }
2650 // CDROM detection fix
2651 }
2652 }
2653 else // must be no media or audio only (for CDs at least)
2654 {
2655 if (bpb.cCylinders <= DisketteCylinders) // floppies will always be 80
2656 {
2657 // or less cylinders
2658 if (bpb.bSectorsPerCluster != OpticalSectorsPerCluster)
2659 bpb.fsDeviceAttr |= FloppyType;
2660 else
2661 bpb.fsDeviceAttr |= OpticalType;
2662 }
2663 }
2664
2665 //Enable error popups again
2666 DosError(FERR_ENABLEEXCEPTION | FERR_ENABLEHARDERR);
2667
2668 free(pfsqbuf2);
2669 }
2670 else
2671 {// non removable or CD type. maybe RAM disk
2672 if (!(bpb.fsDeviceAttr & CDType)) // if NOT CD
2673 {
2674 if (bpb.cFATs == 1) // is there only one FAT?
2675 bpb.fsDeviceAttr |= VDISKType; // -> RAM disk
2676 }
2677 }
2678 }
2679
2680
2681 /*
2682 * Determin return value.
2683 */
2684 if (bpb.fsDeviceAttr & FloppyType)
2685 {
2686 ulDriveType = DRIVE_REMOVABLE_W;
2687 /* update floppy cache if A or B */
2688 if (ulDrive <= 1)
2689 ulFloppyMask |= 1 << ulDrive;
2690 }
2691 else if (bpb.fsDeviceAttr & CDType)
2692 {
2693 ulDriveType = DRIVE_CDROM_W;
2694 /* update cdrom cache */
2695 ulCDROMMask |= 1 << ulDrive;
2696 }
2697 else if (bpb.fsDeviceAttr & LanType)
2698 ulDriveType = DRIVE_REMOTE_W;
2699 else if (bpb.fsDeviceAttr & VDISKType)
2700 ulDriveType = DRIVE_RAMDISK_W;
2701 else if (bpb.fsDeviceAttr & OpticalType || bpb.bDeviceType == DEVTYPE_OPTICAL)
2702 ulDriveType = DRIVE_FIXED_W;
2703 else if (bpb.bDeviceType == DEVTYPE_FIXED)
2704 ulDriveType = DRIVE_FIXED_W;
2705 else
2706 ulDriveType = DRIVE_UNKNOWN_W;
2707
2708 return ulDriveType;
2709}
2710//******************************************************************************
2711//Returns bit map where with the mapping of the logical drives
2712//******************************************************************************
2713ULONG OSLibGetLogicalDrives()
2714{
2715 ULONG ulDriveNum = 0; /* Drive number (A=1, B=2, C=3, ...) */
2716 ULONG ulDriveMap = 0; /* Mapping of valid drives */
2717 APIRET rc;
2718
2719 rc = DosQueryCurrentDisk(&ulDriveNum, &ulDriveMap);
2720 if(rc) {
2721 DebugInt3();
2722 SetLastError(error2WinError(rc));
2723 return 0;
2724 }
2725 return ulDriveMap;
2726}
2727//******************************************************************************
2728//******************************************************************************
2729ULONG OSLibDosQueryCurrentDisk()
2730
2731{
2732 ULONG ulDriveNum = 0; /* Drive number (A=1, B=2, C=3, ...) */
2733 ULONG ulDriveMap = 0; /* Mapping of valid drives */
2734 APIRET rc;
2735
2736 rc = DosQueryCurrentDisk(&ulDriveNum, &ulDriveMap);
2737 if(rc) {
2738 DebugInt3();
2739 SetLastError(error2WinError(rc));
2740 return 0;
2741 }
2742 return ulDriveNum;
2743}
2744//******************************************************************************
2745//******************************************************************************
2746BOOL OSLibDosCreatePipe(PHANDLE phfRead,
2747 PHANDLE phfWrite,
2748 LPSECURITY_ATTRIBUTES lpsa,
2749 DWORD dwSize)
2750{
2751 APIRET rc;
2752
2753 dprintf(("DosCreatePipe(%08xh,%08xh,%08xh)\n",
2754 phfRead,
2755 phfWrite,
2756 dwSize));
2757
2758 // select default buffer size
2759 if (dwSize == 0)
2760 dwSize = 4096;
2761
2762 rc = DosCreatePipe(phfRead,
2763 phfWrite,
2764 dwSize);
2765 dprintf(("DosCreatePipe rc=%d",rc));
2766 if (rc)
2767 {
2768 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER_W));
2769 return -1; // INVALID_HANDLE_VALUE
2770 }
2771 SetLastError(ERROR_SUCCESS_W);
2772 return NO_ERROR;
2773}
2774//******************************************************************************
2775//******************************************************************************
2776DWORD SYSTEM OSLibDosDevIOCtl( DWORD hFile, DWORD dwCat, DWORD dwFunc,
2777 PVOID pParm, DWORD dwParmMaxLen, DWORD *pdwParmLen,
2778 PVOID pData, DWORD dwDataMaxLen, DWORD *pdwDataLen)
2779{
2780 APIRET rc;
2781 PVOID pTiledParm = pParm;
2782 BOOL flagTiledParm = FALSE;
2783 PVOID pTiledData = pData;
2784 BOOL flagTiledData = FALSE;
2785
2786#if 1
2787 /*
2788 * Quick and Dirty Fix!
2789 * TO BE REMOVED!
2790 *
2791 * On some VPC installation without CDROM we seem to
2792 * use a concidrable amount of time during Win2k shutdown.
2793 * No idea why, but it has to do with CDROM we think.
2794 *
2795 * So, let's just fail all IOCtls to CD01 if there aren't any
2796 * CDROMs in the system.
2797 *
2798 */
2799
2800 /*
2801 * Check for CD drives
2802 * We don't have to this everytime. I mean, the os2cdrom.dmd is
2803 * exactly very dynamic when it comes to this info.
2804 */
2805 if (cdDrvLtr.drive_count == 0xffff)
2806 {
2807 HFILE hCDRom2;
2808 ULONG ulAction = 0;
2809
2810 if (DosOpen("\\DEV\\CD-ROM2$", &hCDRom2, &ulAction, 0,
2811 FILE_NORMAL, OPEN_ACTION_OPEN_IF_EXISTS,
2812 OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY, NULL)
2813 == NO_ERROR)
2814 {
2815 ULONG cbData = sizeof(cdDrvLtr);
2816 rc = DosDevIOCtl(hCDRom2,
2817 IOC_CDROM_2,
2818 IOCD_RETURN_DRIVE_LETTER,
2819 NULL, 0, NULL,
2820 (PVOID)&cdDrvLtr, sizeof(cdDrvLtr), &cbData);
2821 DosClose(hCDRom2);
2822 }
2823 else
2824 cdDrvLtr.drive_count = 0;
2825 }
2826
2827 if ( cdDrvLtr.drive_count == 0
2828 && (dwCat == IOCTL_CDROMDISK
2829 || (dwCat == IOCTL_CDROMAUDIO
2830 && dwParmMaxLen >= 4 && strncmp((char*)pParm, "CD01", 4))
2831 )
2832 )
2833 {
2834 /* just return some error code */
2835 return ERROR_BAD_COMMAND;
2836 }
2837
2838#endif
2839
2840#define MEM_TILED_CEILING 0x1fffffff
2841
2842 // bounce buffer support
2843 // make sure no parameter or data buffer can pass the tiled memory region
2844 // barrier (usually 512MB). OS/2 kernel does not correctly translate these
2845 // addresses to a 16:16 address used in device driver land. In fact,
2846 // DosDevIOCtl is not a high memory enabled API!
2847
2848 if (pTiledParm && (((DWORD)pTiledParm + max(dwParmMaxLen, *pdwParmLen)) > MEM_TILED_CEILING))
2849 {
2850 rc = DosAllocMem(&pTiledParm, dwParmMaxLen, PAG_READ | PAG_WRITE);
2851 if (rc)
2852 goto _exit_ioctl;
2853
2854 flagTiledParm = TRUE;
2855 }
2856
2857 if (pTiledData && (((DWORD)pTiledData + max(dwDataMaxLen, *pdwDataLen)) > MEM_TILED_CEILING))
2858 {
2859 rc = DosAllocMem(&pTiledData, dwDataMaxLen, PAG_READ | PAG_WRITE);
2860 if (rc)
2861 goto _exit_ioctl;
2862
2863 flagTiledData = TRUE;
2864 }
2865
2866 // copy data from real buffers to
2867 // bounce buffers if necessary
2868 if (pTiledParm != pParm)
2869 memcpy(pTiledParm, pParm, *pdwParmLen);
2870
2871 if (pTiledData != pData)
2872 memcpy(pTiledData, pData, *pdwDataLen);
2873
2874
2875 rc = DosDevIOCtl( (HFILE)hFile, dwCat, dwFunc,
2876 pParm, dwParmMaxLen, pdwParmLen,
2877 pData, dwDataMaxLen, pdwDataLen);
2878
2879 // copy data from bounce buffers to real
2880 // target buffers if necessary
2881 if (pTiledParm != pParm)
2882 memcpy(pParm, pTiledParm, *pdwParmLen);
2883
2884 if (pTiledData != pData)
2885 memcpy(pData, pTiledData, *pdwDataLen);
2886
2887
2888 _exit_ioctl:
2889
2890 // deallocate bounce buffers
2891 if (flagTiledParm)
2892 DosFreeMem(pTiledParm);
2893
2894 if (flagTiledData)
2895 DosFreeMem(pTiledData);
2896
2897 rc = error2WinError(rc, ERROR_INVALID_HANDLE);
2898 SetLastError(rc);
2899 return (DWORD)rc;
2900}
2901
2902/**
2903 * Pure wrapper for DosQueryModulName which returns the OS/2 returncode.
2904 * @returns Returncode from DosQueryModuleName.
2905 * @param hModule Handle of the module which name we query.
2906 * @param cchName Length of the output name buffer.
2907 * @param pszname Pointer to the output name buffer.
2908 * @status Completely implemented.
2909 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
2910 */
2911ULONG OSLibDosQueryModuleName(ULONG hModule, int cchName, char *pszName)
2912{
2913 return DosQueryModuleName(hModule, cchName, pszName);
2914}
2915
2916
2917HINSTANCE OSLibDosLoadModule(LPSTR szModName)
2918{
2919 APIRET rc;
2920 HMODULE hModule = NULLHANDLE;
2921 char name[ CCHMAXPATH ];
2922
2923 rc = DosLoadModule(name, CCHMAXPATH, szModName, &hModule);
2924 if(rc) {
2925 SetLastError(error2WinError(rc,ERROR_FILE_NOT_FOUND));
2926 return 0;
2927 }
2928 SetLastError(ERROR_SUCCESS_W);
2929 return hModule;
2930}
2931//******************************************************************************
2932//******************************************************************************
2933void OSLibDosFreeModule(HINSTANCE hinst)
2934{
2935 DosFreeModule(hinst);
2936}
2937//******************************************************************************
2938//******************************************************************************
2939ULONG OSLibDosQuerySysInfo(ULONG iStart, ULONG iLast, PVOID pBuf, ULONG cbBuf)
2940{
2941 APIRET rc;
2942
2943 rc = DosQuerySysInfo(iStart, iLast, pBuf, cbBuf);
2944 SetLastError(error2WinError(rc,ERROR_INVALID_HANDLE));
2945 return rc;
2946}
2947//******************************************************************************
2948//returned length is number of characters required or used for current dir
2949//*excluding* terminator
2950//******************************************************************************
2951ULONG OSLibDosQueryDir(DWORD length, LPSTR lpszCurDir)
2952{
2953 ULONG drivemap, currentdisk, len;
2954 char *lpszCurDriveAndDir = lpszCurDir +3;
2955 APIRET rc;
2956
2957 len = (length > 3) ? length - 3 : 0;
2958
2959 rc = DosQueryCurrentDir(0, lpszCurDriveAndDir, &len);
2960 if(rc != ERROR_BUFFER_OVERFLOW)
2961 {
2962 if(rc)
2963 {
2964 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER));
2965 return 0;
2966 }
2967 len = strlen(lpszCurDriveAndDir) + 3;
2968
2969 // Dir returned by DosQueryCurDir doesn't include drive, so add it
2970 DosQueryCurrentDisk(&currentdisk, &drivemap);
2971
2972 if(isupper(lpszCurDir[3])) {
2973 lpszCurDir[0] = (char)('A' - 1 + currentdisk);
2974 }
2975 else lpszCurDir[0] = (char)('a' - 1 + currentdisk);
2976
2977 lpszCurDir[1] = ':';
2978 lpszCurDir[2] = '\\';
2979 }
2980 else len += 3; // + 3 since DosQueryCurDir doesn't include drive
2981
2982 SetLastError(ERROR_SUCCESS_W);
2983 return len;
2984}
2985//******************************************************************************
2986//******************************************************************************
2987BOOL OSLibDosBeep(DWORD ulFreq, DWORD ulDuration)
2988{
2989 APIRET rc;
2990
2991 if (ulDuration == -1)
2992 {
2993 SetLastError(ERROR_NOT_SUPPORTED_W);
2994 return FALSE;
2995 }
2996 rc = DosBeep(ulFreq, ulDuration);
2997 SetLastError(error2WinError(rc,ERROR_INVALID_HANDLE));
2998
2999 return (rc == 0);
3000}
3001//******************************************************************************
3002//******************************************************************************
3003ULONG OSLibDosGetModuleFileName(HMODULE hModule, LPTSTR lpszPath, DWORD cchPath)
3004{
3005 PTIB pTIB;
3006 PPIB pPIB;
3007 APIRET rc;
3008
3009 if(hModule == -1 || hModule == 0)
3010 {
3011 DosGetInfoBlocks(&pTIB, &pPIB);
3012 hModule = pPIB->pib_hmte;
3013 }
3014 *lpszPath = 0;
3015 rc = DosQueryModuleName(hModule, cchPath, lpszPath);
3016
3017 DWORD len = strlen(lpszPath);
3018 SetLastError(error2WinError(rc,ERROR_INVALID_HANDLE));
3019 return len;
3020}
3021//******************************************************************************
3022//******************************************************************************
3023ULONG OSLibDosGetProcAddress(HMODULE hModule, LPCSTR lpszProc)
3024{
3025 APIRET rc;
3026 PFN pfn = NULL;
3027 ULONG ordinal = (((ULONG)lpszProc) <= 0xFFFF) ? (ULONG)lpszProc : 0;
3028 HMODULE hmod = (HMODULE)hModule;
3029
3030 rc = DosQueryProcAddr( hmod, ordinal, (PSZ)lpszProc, &pfn );
3031 if(rc == ERROR_INVALID_HANDLE && pfn == NULL) {
3032 CHAR pszError[32], pszModule[CCHMAXPATH];
3033
3034 if(DosQueryModuleName( hmod, CCHMAXPATH, pszModule ) == 0 &&
3035 DosLoadModule( pszError, 32, pszModule, &hmod ) == 0)
3036 {
3037 rc = DosQueryProcAddr(hmod, ordinal, (PSZ)lpszProc, &pfn);
3038 }
3039 }
3040 SetLastError(error2WinError(rc,ERROR_INVALID_HANDLE));
3041
3042 return (ULONG)pfn;
3043}
3044//******************************************************************************
3045//******************************************************************************
3046BOOL OSLibDosSetThreadAffinity(DWORD dwThreadAffinityMask)
3047{
3048 static PROC_DosSetThreadAffinity pfnDosSetThreadAffinity = NULL;
3049 static BOOL fInit = FALSE;
3050 MPAFFINITY mask;
3051 APIRET rc;
3052
3053 if(fInit == FALSE && pfnDosSetThreadAffinity == NULL)
3054 {
3055 ULONG nrCPUs;
3056
3057 rc = DosQuerySysInfo(QSV_NUMPROCESSORS, QSV_NUMPROCESSORS, &nrCPUs, sizeof(nrCPUs));
3058 if (rc != 0 || nrCPUs == 1)
3059 {//not supported
3060 fInit = TRUE;
3061 SetLastError(ERROR_SUCCESS_W);
3062 return TRUE;
3063 }
3064
3065 HMODULE hDoscalls;
3066 if(DosQueryModuleHandle("DOSCALLS", &hDoscalls) == NO_ERROR) {
3067 DosQueryProcAddr(hDoscalls, 564, NULL, (PFN *)&pfnDosSetThreadAffinity);
3068 }
3069 fInit = TRUE;
3070 }
3071 if(fInit && pfnDosSetThreadAffinity == NULL) {
3072 SetLastError(ERROR_SUCCESS_W);
3073 return TRUE;
3074 }
3075 USHORT sel = RestoreOS2FS();
3076
3077 mask.mask[0] = dwThreadAffinityMask;
3078 mask.mask[1] = 0; //TODO: this might not be a good idea, but then again, not many people have > 32 cpus
3079
3080 rc = pfnDosSetThreadAffinity(&mask);
3081 SetFS(sel);
3082
3083 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER));
3084 return (rc == NO_ERROR);
3085}
3086//******************************************************************************
3087//******************************************************************************
3088BOOL OSLibDosQueryAffinity(DWORD fMaskType, DWORD *pdwThreadAffinityMask)
3089{
3090 static PROC_DosQueryThreadAffinity pfnDosQueryThreadAffinity = NULL;
3091 static BOOL fInit = FALSE;
3092 MPAFFINITY mask;
3093 APIRET rc;
3094
3095 if(fInit == FALSE && pfnDosQueryThreadAffinity == NULL)
3096 {
3097 ULONG nrCPUs;
3098
3099 rc = DosQuerySysInfo(QSV_NUMPROCESSORS, QSV_NUMPROCESSORS, &nrCPUs, sizeof(nrCPUs));
3100 if (rc != 0 || nrCPUs == 1)
3101 {//not supported
3102 fInit = TRUE;
3103 *pdwThreadAffinityMask = 1;
3104 SetLastError(ERROR_SUCCESS_W);
3105 return TRUE;
3106 }
3107
3108 HMODULE hDoscalls;
3109 if(DosQueryModuleHandle("DOSCALLS", &hDoscalls) == NO_ERROR) {
3110 DosQueryProcAddr(hDoscalls, 563, NULL, (PFN *)&pfnDosQueryThreadAffinity);
3111 }
3112 fInit = TRUE;
3113 }
3114 if(fInit && pfnDosQueryThreadAffinity == NULL) {
3115 *pdwThreadAffinityMask = 1;
3116 SetLastError(ERROR_SUCCESS_W);
3117 return TRUE;
3118 }
3119
3120 ULONG scope = (fMaskType == MASK_SYSTEM) ? AFNTY_SYSTEM : AFNTY_THREAD;
3121
3122 USHORT sel = RestoreOS2FS();
3123
3124 rc = pfnDosQueryThreadAffinity(scope, &mask);
3125 SetFS(sel);
3126
3127 if(rc == NO_ERROR) {
3128 *pdwThreadAffinityMask = mask.mask[0];
3129 }
3130
3131 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER));
3132 return (rc == NO_ERROR);
3133}
3134//******************************************************************************
3135//******************************************************************************
3136DWORD OSLibDosSetPriority(ULONG tid, int priority)
3137{
3138 DWORD ret, os2priorityclass;
3139 LONG os2prioritydelta;
3140 APIRET rc;
3141
3142 switch(priority)
3143 {
3144 case THREAD_PRIORITY_IDLE_W:
3145 os2priorityclass = PRTYC_IDLETIME;
3146 os2prioritydelta = 0;
3147 break;
3148 case THREAD_PRIORITY_LOWEST_W:
3149 os2priorityclass = PRTYC_REGULAR;
3150 os2prioritydelta = PRTYD_MINIMUM;
3151 break;
3152 case THREAD_PRIORITY_BELOW_NORMAL_W:
3153 os2priorityclass = PRTYC_REGULAR;
3154 os2prioritydelta = -15;
3155 break;
3156 case THREAD_PRIORITY_NORMAL_W:
3157 os2priorityclass = PRTYC_REGULAR;
3158 os2prioritydelta = 0;
3159 break;
3160 case THREAD_PRIORITY_ABOVE_NORMAL_W:
3161 os2priorityclass = PRTYC_REGULAR;
3162 os2prioritydelta = 15;
3163 break;
3164 case THREAD_PRIORITY_HIGHEST_W:
3165 os2priorityclass = PRTYC_REGULAR;
3166 os2prioritydelta = PRTYD_MAXIMUM;
3167 break;
3168 case THREAD_PRIORITY_TIME_CRITICAL_W:
3169 os2priorityclass = PRTYC_TIMECRITICAL;
3170 os2prioritydelta = 0;
3171 break;
3172 default:
3173 dprintf(("!WARNING!: Invalid priority!!"));
3174 SetLastError(ERROR_INVALID_PARAMETER_W);
3175 return ERROR_INVALID_PARAMETER_W;
3176 }
3177 rc = DosSetPriority(PRTYS_THREAD, os2priorityclass, os2prioritydelta, tid);
3178 ret = error2WinError(rc, ERROR_INVALID_PARAMETER);
3179 SetLastError(ret);
3180 return ret;
3181}
3182//******************************************************************************
3183//******************************************************************************
3184void OSLibDosSleep(ULONG msecs)
3185{
3186 DosSleep(msecs);
3187}
3188//******************************************************************************
3189//******************************************************************************
3190void OSLibDosExitThread(ULONG retcode)
3191{
3192 DosExit(EXIT_THREAD, retcode);
3193}
3194//******************************************************************************
3195//******************************************************************************
3196DWORD OSLibDosDevConfig(PVOID pdevinfo,
3197 ULONG item)
3198{
3199 return (DWORD)DosDevConfig(pdevinfo, item);
3200}
3201//******************************************************************************
3202//******************************************************************************
3203DWORD OSLibDosGetNumPhysDrives()
3204{
3205 USHORT usNumDrives = 0; /* Data return buffer */
3206 ULONG ulDataLen = sizeof(USHORT); /* Data return buffer length */
3207 APIRET rc = NO_ERROR; /* Return code */
3208
3209 /* Request a count of the number of partitionable disks in the system */
3210
3211 rc = DosPhysicalDisk(INFO_COUNT_PARTITIONABLE_DISKS,
3212 &usNumDrives,
3213 ulDataLen,
3214 NULL, /* No parameter for this function */
3215 0L);
3216
3217 if (rc != NO_ERROR) {
3218 dprintf(("DosPhysicalDisk error: return code = %u\n", rc));
3219 return 0;
3220 }
3221 else {
3222 dprintf(("DosPhysicalDisk: %u partitionable disk(s)\n",usNumDrives));
3223 }
3224 return usNumDrives;
3225}
3226//******************************************************************************
3227//******************************************************************************
3228
Note: See TracBrowser for help on using the repository browser.