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

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

Use DosOpenL if available

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