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

Last change on this file since 7777 was 7777, checked in by sandervl, 24 years ago

VP: GetDriveType fix for detection cdrom drives under certain circumstances (when cdrom is not the last drive letter)

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