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

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

No longer use DosError; IOCTL_DISK_GET_DRIVE_GEOMETRY must return ERROR_MEDIA_CHANGED when floppy has been changed

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