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

Last change on this file since 6968 was 6968, checked in by phaller, 24 years ago

added error codes 34 and 23

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