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

Last change on this file since 4698 was 4698, checked in by sandervl, 25 years ago

Workaround for OS/2 shared memory name limitation (no colons)

File size: 66.1 KB
Line 
1/* $Id: oslibdos.cpp,v 1.51 2000-11-25 16:56:57 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_NPIPES
21#include <os2wrap.h> //Odin32 OS/2 api wrappers
22#include <stdlib.h>
23#include <stdio.h>
24#include <string.h>
25#include <ctype.h>
26#include <win32api.h>
27#include <winconst.h>
28#include <misc.h>
29#include "initterm.h"
30#include "oslibdos.h"
31#include "dosqss.h"
32
33#define DBG_LOCALLOG DBG_oslibdos
34#include "dbglocal.h"
35
36static PROC_DosSetFileSizeL DosSetFileSizeLProc = 0;
37static PROC_DosSetFilePtrL DosSetFilePtrLProc = 0;
38static PROC_DosSetFileLocksL DosSetFileLocksLProc = 0;
39static BOOL f64BitIO = FALSE;
40//******************************************************************************
41//******************************************************************************
42void OSLibInitWSeBFileIO()
43{
44 HMODULE hDoscalls;
45
46 if(DosQueryModuleHandle("DOSCALLS", &hDoscalls) != NO_ERROR) {
47 return;
48 }
49 if(DosQueryProcAddr(hDoscalls, 989, NULL, (PFN *)&DosSetFileSizeLProc) != NO_ERROR) {
50 return;
51 }
52 if(DosQueryProcAddr(hDoscalls, 988, NULL, (PFN *)&DosSetFilePtrLProc) != NO_ERROR) {
53 return;
54 }
55 if(DosQueryProcAddr(hDoscalls, 986, NULL, (PFN *)&DosSetFileLocksLProc) != NO_ERROR) {
56 return;
57 }
58 f64BitIO = TRUE;
59}
60//******************************************************************************
61//******************************************************************************
62APIRET OdinDosSetFileSizeL(HFILE hFile, LONGLONG cbSize)
63{
64 APIRET yyrc;
65 USHORT sel = RestoreOS2FS();
66
67 yyrc = DosSetFileSizeLProc(hFile, cbSize);
68 SetFS(sel);
69
70 return yyrc;
71}
72//******************************************************************************
73//******************************************************************************
74APIRET OdinDosSetFilePtrL(HFILE hFile, LONGLONG ib, ULONG method, PLONGLONG ibActual)
75{
76 APIRET yyrc;
77 USHORT sel = RestoreOS2FS();
78
79 yyrc = DosSetFilePtrLProc(hFile, ib, method, ibActual);
80 SetFS(sel);
81
82 return yyrc;
83}
84//******************************************************************************
85//******************************************************************************
86APIRET OdinDosSetFileLocksL(HFILE hFile, PFILELOCKL pflUnlock, PFILELOCKL pflLock,
87 ULONG timeout, ULONG flags)
88{
89 APIRET yyrc;
90 USHORT sel = RestoreOS2FS();
91
92 yyrc = DosSetFileLocksLProc(hFile, pflUnlock, pflLock, timeout, flags);
93 SetFS(sel);
94
95 return yyrc;
96}
97//******************************************************************************
98// translate OS/2 error codes to Windows codes
99// NOTE: add all codes you need, list is not complete!
100//******************************************************************************
101DWORD error2WinError(APIRET rc,DWORD defaultCode = ERROR_NOT_ENOUGH_MEMORY_W)
102{
103 switch (rc)
104 {
105 case NO_ERROR: //0
106 return ERROR_SUCCESS_W;
107
108 case ERROR_INVALID_FUNCTION: //1
109 return ERROR_INVALID_FUNCTION_W;
110
111 case ERROR_FILE_NOT_FOUND: //2
112 return ERROR_FILE_NOT_FOUND_W;
113
114 case ERROR_PATH_NOT_FOUND: //3
115 return ERROR_PATH_NOT_FOUND_W;
116
117 case ERROR_TOO_MANY_OPEN_FILES: //4
118 return ERROR_TOO_MANY_OPEN_FILES_W;
119
120 case ERROR_ACCESS_DENIED: //5
121 return ERROR_ACCESS_DENIED_W;
122
123 case ERROR_INVALID_HANDLE: //6
124 return ERROR_INVALID_HANDLE_W;
125
126 case ERROR_NOT_ENOUGH_MEMORY: //8
127 return ERROR_NOT_ENOUGH_MEMORY_W;
128
129 case ERROR_BAD_FORMAT: //11
130 return ERROR_BAD_FORMAT_W;
131
132 case ERROR_INVALID_ACCESS: //12
133 return ERROR_INVALID_ACCESS_W;
134
135 case ERROR_NO_MORE_FILES: //18
136 return ERROR_NO_MORE_FILES_W;
137
138 case ERROR_WRITE_PROTECT: //19
139 return ERROR_WRITE_PROTECT_W;
140
141 case ERROR_NOT_DOS_DISK: //26
142 return ERROR_NOT_DOS_DISK_W;
143
144 case ERROR_WRITE_FAULT: //29
145 return ERROR_WRITE_FAULT_W;
146
147 case ERROR_SHARING_VIOLATION: //32
148 return ERROR_SHARING_VIOLATION_W;
149
150 case ERROR_LOCK_VIOLATION: //32
151 return ERROR_LOCK_VIOLATION_W;
152
153 case ERROR_SHARING_BUFFER_EXCEEDED: //36
154 return ERROR_SHARING_BUFFER_EXCEEDED_W;
155
156 case ERROR_CANNOT_MAKE: //82
157 return ERROR_CANNOT_MAKE_W;
158
159 case ERROR_OUT_OF_STRUCTURES: //84
160 return ERROR_OUT_OF_STRUCTURES_W;
161
162 case ERROR_INVALID_PARAMETER: //87
163 return ERROR_INVALID_PARAMETER_W;
164
165 case ERROR_INTERRUPT: //95
166 return ERROR_INVALID_AT_INTERRUPT_TIME_W; //CB: right???
167
168 case ERROR_DEVICE_IN_USE: //99
169 return ERROR_DEVICE_IN_USE_W;
170
171 case ERROR_DRIVE_LOCKED: //108
172 return ERROR_DRIVE_LOCKED_W;
173
174 case ERROR_BROKEN_PIPE: //109
175 return ERROR_BROKEN_PIPE_W;
176
177 case ERROR_OPEN_FAILED: //110
178 return ERROR_OPEN_FAILED_W;
179
180 case ERROR_BUFFER_OVERFLOW: //111
181 return ERROR_BUFFER_OVERFLOW_W;
182
183 case ERROR_DISK_FULL: //112
184 return ERROR_DISK_FULL_W;
185
186 case ERROR_NO_MORE_SEARCH_HANDLES: //113
187 return ERROR_NO_MORE_SEARCH_HANDLES_W;
188
189 case ERROR_SEM_TIMEOUT: //121
190 return ERROR_SEM_TIMEOUT_W;
191
192 case ERROR_DIRECT_ACCESS_HANDLE: //130
193 return ERROR_DIRECT_ACCESS_HANDLE_W;
194
195 case ERROR_NEGATIVE_SEEK: //131
196 return ERROR_NEGATIVE_SEEK;
197
198 case ERROR_SEEK_ON_DEVICE: //132
199 return ERROR_SEEK_ON_DEVICE_W;
200
201 case ERROR_DISCARDED: //157
202 return ERROR_DISCARDED_W;
203
204 case ERROR_FILENAME_EXCED_RANGE: //206
205 return ERROR_FILENAME_EXCED_RANGE_W;
206
207 case ERROR_META_EXPANSION_TOO_LONG: //208
208 return ERROR_META_EXPANSION_TOO_LONG_W;
209
210 case ERROR_BAD_PIPE: //230
211 return ERROR_BAD_PIPE_W;
212
213 case ERROR_PIPE_BUSY: //231
214 return ERROR_PIPE_BUSY_W;
215
216 case ERROR_NO_DATA: //232
217 return ERROR_NO_DATA_W;
218
219 case ERROR_PIPE_NOT_CONNECTED: //233
220 return ERROR_PIPE_NOT_CONNECTED_W;
221
222 case ERROR_MORE_DATA: //234
223 return ERROR_MORE_DATA_W;
224
225 case ERROR_INVALID_EA_NAME: //254
226 return ERROR_INVALID_EA_NAME_W;
227
228 case ERROR_EA_LIST_INCONSISTENT: //255
229 return ERROR_EA_LIST_INCONSISTENT_W;
230
231 case ERROR_EAS_DIDNT_FIT: //275
232 return ERROR_EAS_DIDNT_FIT;
233
234 default:
235 dprintf(("WARNING: error2WinError: error %d not included!!!!", rc));
236 return defaultCode;
237 }
238}
239//******************************************************************************
240//TODO: Assumes entire memory range has the same protection flags!
241//TODO: Check if this works for code aliases...
242//******************************************************************************
243DWORD OSLibDosAliasMem(LPVOID pb, ULONG cb, LPVOID *ppbAlias, ULONG fl)
244{
245 DWORD rc;
246 DWORD attr;
247 DWORD size = cb;
248
249 cb = (cb-1) & ~0xfff;
250 cb+= PAGE_SIZE;
251
252 rc = DosQueryMem(pb, &size, &attr);
253 if(rc) {
254 dprintf(("OSLibDosAliasMem: DosQueryMem %x %x return %d", pb, size, rc));
255 return rc;
256 }
257 size = (size-1) & ~0xfff;
258 size+= PAGE_SIZE;
259 if(size != cb) {
260 dprintf(("ERROR: OSLibDosAliasMem: size != cb (%x!=%x)!!!!!!!!", size, cb));
261 //ignore this and continue return 5;
262 attr = fl; //just use original protection flags (NOT CORRECT)
263 }
264 attr &= (PAG_READ|PAG_WRITE|PAG_EXECUTE|PAG_GUARD|PAG_DEFAULT);
265 if(attr != fl) {
266 rc = DosSetMem(pb, size, fl);
267 if(rc) {
268 dprintf(("OSLibDosAliasMem: DosSetMem %x %x return %d", pb, size, rc));
269 attr = fl;
270 //just continue for now
271 //return rc;
272 }
273 }
274 rc = DosAliasMem(pb, cb, ppbAlias, 2);
275 if(rc) {
276 dprintf(("OSLibDosAliasMem: DosAliasMem %x %x returned %d", pb, cb, rc));
277 return rc;
278 }
279 if(attr != fl) {
280 rc = DosSetMem(pb, size, attr);
281 if(rc) {
282 dprintf(("OSLibDosAliasMem: DosSetMem (2) %x %x return %d", pb, size, rc));
283 return rc;
284 }
285 }
286 return 0;
287}
288//******************************************************************************
289//NT returns addresses aligned at 64k, so we do too.
290//******************************************************************************
291DWORD OSLibDosAllocMem(LPVOID *lplpMemAddr, DWORD size, DWORD flags)
292{
293 LPVOID memaddr;
294 DWORD offset;
295 APIRET rc;
296
297 rc = DosAllocMem(&memaddr, size, PAG_READ | flAllocMem);
298 if(rc) {
299 return rc;
300 }
301 DosEnterCritSec();
302 DosFreeMem(memaddr);
303 offset = (DWORD)memaddr & 0xFFFF;
304 if(offset) {
305 DosAllocMem(&memaddr, 64*1024 - offset, PAG_READ | flAllocMem);
306 }
307 rc = DosAllocMem(lplpMemAddr, size, flags | flAllocMem);
308 DosExitCritSec();
309 if((DWORD)*lplpMemAddr & 0xFFFF) {//still not at 64k boundary?
310 DosFreeMem(*lplpMemAddr);
311 rc = OSLibDosAllocMem(lplpMemAddr, size, flags);
312 }
313 if(offset) {
314 DosFreeMem(memaddr);
315 }
316
317 return rc;
318}
319//******************************************************************************
320//******************************************************************************
321DWORD OSLibDosFreeMem(LPVOID lpMemAddr)
322{
323 return DosFreeMem(lpMemAddr);
324}
325//******************************************************************************
326//NOTE: If name == NULL, allocated gettable unnamed shared memory
327//OS/2 returns error 123 (invalid name) if the shared memory name includes
328//colons. We need to replace them with underscores.
329//******************************************************************************
330DWORD OSLibDosAllocSharedMem(LPVOID *lplpMemAddr, DWORD size, DWORD flags, LPSTR name)
331{
332 APIRET rc;
333 char *sharedmemname = NULL, *tmp;
334
335 if(name) {
336 sharedmemname = (char *)malloc(strlen(name) + 16);
337 strcpy(sharedmemname, "\\SHAREMEM\\");
338 strcat(sharedmemname, name);
339 }
340 else flags |= OBJ_GETTABLE;
341
342 //SvL: Colons are unacceptable in shared memory names (for whatever reason)
343 tmp = sharedmemname;
344 while(*tmp != 0) {
345 if(*tmp == ':') {
346 *tmp = '_';
347 }
348 tmp++;
349 }
350
351 rc = DosAllocSharedMem(lplpMemAddr, sharedmemname, size, flags);
352 if(name) {
353 free(sharedmemname);
354 }
355 return rc;
356}
357//******************************************************************************
358//NOTE: If name == NULL, assume gettable unnamed shared memory
359//******************************************************************************
360DWORD OSLibDosGetNamedSharedMem(LPVOID *lplpMemAddr, LPSTR name)
361{
362 APIRET rc;
363 char *sharedmemname = NULL, *tmp;
364
365 if(name) {
366 sharedmemname = (char *)malloc(strlen(name) + 16);
367 strcpy(sharedmemname, "\\SHAREMEM\\");
368 strcat(sharedmemname, name);
369
370 //SvL: Colons are unacceptable in shared memory names (for whatever reason)
371 tmp = sharedmemname;
372 while(*tmp != 0) {
373 if(*tmp == ':') {
374 *tmp = '_';
375 }
376 tmp++;
377 }
378 rc = DosGetNamedSharedMem(lplpMemAddr, sharedmemname, PAG_READ|PAG_WRITE);
379 if(name) {
380 free(sharedmemname);
381 }
382 }
383 else rc = DosGetSharedMem((LPVOID)*(DWORD *)lplpMemAddr, PAG_READ|PAG_WRITE);
384
385 return rc;
386}
387//******************************************************************************
388//******************************************************************************
389DWORD OSLibDosQueryMem(LPVOID lpMemAddr, DWORD *lpRangeSize, DWORD *lpAttr)
390{
391 return DosQueryMem(lpMemAddr, lpRangeSize, lpAttr);
392}
393//******************************************************************************
394//******************************************************************************
395DWORD OSLibDosSetMem(LPVOID lpMemAddr, DWORD size, DWORD flags)
396{
397 APIRET rc;
398
399 rc = DosSetMem(lpMemAddr, size, flags);
400 switch(rc) {
401 case ERROR_INVALID_ADDRESS:
402 return OSLIB_ERROR_INVALID_ADDRESS;
403 case ERROR_ACCESS_DENIED:
404 return OSLIB_ERROR_ACCESS_DENIED;
405 default:
406 return rc;
407 }
408}
409//******************************************************************************
410//******************************************************************************
411DWORD OSLibDosOpen(char *lpszFileName, DWORD flags)
412{
413 APIRET rc;
414 HFILE hFile;
415 ULONG ulAction;
416 DWORD os2flags = OPEN_FLAGS_NOINHERIT;
417
418
419 if(flags & OSLIB_ACCESS_READONLY)
420 os2flags |= OPEN_ACCESS_READONLY;
421 else
422 if(flags & OSLIB_ACCESS_READWRITE)
423 os2flags |= OPEN_ACCESS_READWRITE;
424
425 if(flags & OSLIB_ACCESS_SHAREDENYNONE)
426 os2flags |= OPEN_SHARE_DENYNONE;
427 else
428 if(flags & OSLIB_ACCESS_SHAREDENYREAD)
429 os2flags |= OPEN_SHARE_DENYREAD;
430 else
431 if(flags & OSLIB_ACCESS_SHAREDENYWRITE)
432 os2flags |= OPEN_SHARE_DENYWRITE;
433
434tryopen:
435 rc = DosOpen(lpszFileName, /* File path name */
436 &hFile, /* File handle */
437 &ulAction, /* Action taken */
438 0L, /* File primary allocation */
439 0L, /* File attribute */
440 OPEN_ACTION_FAIL_IF_NEW |
441 OPEN_ACTION_OPEN_IF_EXISTS, /* Open function type */
442 os2flags,
443 0L); /* No extended attribute */
444
445 if(rc) {
446 if(rc == ERROR_TOO_MANY_OPEN_FILES) {
447 ULONG CurMaxFH;
448 LONG ReqCount = 32;
449
450 rc = DosSetRelMaxFH(&ReqCount, &CurMaxFH);
451 if(rc) {
452 dprintf(("DosSetRelMaxFH returned %d", rc));
453 return 0;
454 }
455 dprintf(("DosOpen failed -> increased nr open files to %d", CurMaxFH));
456 goto tryopen;
457 }
458 return 0;
459 }
460 else return hFile;
461}
462//******************************************************************************
463//******************************************************************************
464BOOL OSLibDosClose(DWORD hFile)
465{
466 APIRET rc;
467
468 rc = DosClose(hFile);
469 SetLastError(error2WinError(rc));
470 return (rc == NO_ERROR);
471}
472//******************************************************************************
473//******************************************************************************
474DWORD OSLibDosChangeMaxFileHandles()
475{
476 ULONG CurMaxFH;
477 LONG ReqCount = 0;
478 APIRET rc;
479
480 rc = DosSetRelMaxFH(&ReqCount, &CurMaxFH);
481 if(rc) {
482 dprintf(("DosSetRelMaxFH returned %d", rc));
483 return rc;
484 }
485 if(ReqCount + ODIN_INCREMENT_MAX_FILEHANDLES > CurMaxFH) {
486 ReqCount = CurMaxFH + ODIN_INCREMENT_MAX_FILEHANDLES;
487 rc = DosSetRelMaxFH(&ReqCount, &CurMaxFH);
488 if(rc) {
489 dprintf(("DosSetRelMaxFH returned %d", rc));
490 return rc;
491 }
492 }
493 return 0;
494}
495//******************************************************************************
496//******************************************************************************
497DWORD OSLibDosSetInitialMaxFileHandles(DWORD maxhandles)
498{
499 ULONG CurMaxFH;
500 LONG ReqCount = 0;
501 APIRET rc;
502
503 rc = DosSetRelMaxFH(&ReqCount, &CurMaxFH);
504 if(rc) {
505 dprintf(("DosSetRelMaxFH returned %d", rc));
506 return rc;
507 }
508 if(CurMaxFH < maxhandles) {
509 rc = DosSetMaxFH(maxhandles);
510 if(rc) {
511 dprintf(("DosSetMaxFH returned %d", rc));
512 return rc;
513 }
514 }
515 return 0;
516}
517//******************************************************************************
518//******************************************************************************
519BOOL OSLibDosRead(DWORD hFile, LPVOID lpBuffer, DWORD size, DWORD *nrBytesRead)
520{
521 APIRET rc;
522
523 rc = DosRead(hFile, lpBuffer, size, nrBytesRead);
524 SetLastError(error2WinError(rc));
525 return (rc == NO_ERROR);
526}
527//******************************************************************************
528//******************************************************************************
529BOOL OSLibDosWrite(DWORD hFile, LPVOID lpBuffer, DWORD size, DWORD *nrBytesWritten)
530{
531 APIRET rc;
532
533 rc = DosWrite(hFile, lpBuffer, size, nrBytesWritten);
534 SetLastError(error2WinError(rc));
535 return (rc == NO_ERROR);
536}
537//******************************************************************************
538//******************************************************************************
539DWORD OSLibDosSetFilePtr(DWORD hFile, DWORD offset, DWORD method)
540{
541 DWORD os2method;
542 DWORD newoffset;
543 APIRET rc;
544
545 switch(method)
546 {
547 case OSLIB_SETPTR_FILE_CURRENT:
548 os2method = FILE_CURRENT;
549 break;
550 case OSLIB_SETPTR_FILE_BEGIN:
551 os2method = FILE_BEGIN ;
552 break;
553 case OSLIB_SETPTR_FILE_END:
554 os2method = FILE_END;
555 break;
556 default:
557 return OSLIB_ERROR_INVALID_PARAMETER;
558 }
559
560 rc = DosSetFilePtr(hFile, offset, os2method, &newoffset);
561 if(rc)
562 {
563 SetLastError(error2WinError(rc));
564 return -1;
565 }
566 else return newoffset;
567}
568//******************************************************************************
569//******************************************************************************
570BOOL OSLibDosDelete(char *lpszFileName)
571{
572 APIRET rc;
573
574 rc = DosDelete(lpszFileName);
575 if(rc) {
576 SetLastError(error2WinError(rc));
577 return FALSE;
578 }
579 return TRUE;
580}
581//******************************************************************************
582//******************************************************************************
583BOOL pmDateTimeToFileTime(FDATE *pDate,FTIME *pTime,FILETIME *pFT)
584{
585 USHORT dosTime, dosDate;
586
587 dosTime = *(USHORT*)pTime;
588 dosDate = *(USHORT*)pDate;
589
590 return DosDateTimeToFileTime(dosDate,dosTime,pFT);
591}
592//******************************************************************************
593//******************************************************************************
594#define NOT_NORMAL (FILE_ATTRIBUTE_READONLY_W | \
595 FILE_ATTRIBUTE_HIDDEN_W | \
596 FILE_ATTRIBUTE_SYSTEM_W | \
597 FILE_ATTRIBUTE_ARCHIVE_W)
598
599inline DWORD pm2WinFileAttributes(DWORD attrFile)
600{
601 DWORD res = 0;
602
603 if (!(attrFile & NOT_NORMAL))
604 res |= FILE_ATTRIBUTE_NORMAL_W;
605 if (attrFile & FILE_READONLY)
606 res |= FILE_ATTRIBUTE_READONLY_W;
607 if (attrFile & FILE_HIDDEN)
608 res |= FILE_ATTRIBUTE_HIDDEN_W;
609 if (attrFile & FILE_SYSTEM)
610 res |= FILE_ATTRIBUTE_SYSTEM_W;
611 if (attrFile & FILE_DIRECTORY)
612 res |= FILE_ATTRIBUTE_DIRECTORY_W;
613 if (attrFile & FILE_ARCHIVED)
614 res |= FILE_ATTRIBUTE_ARCHIVE_W;
615
616 //CB: not used: FILE_ATTRIBUTE_COMPRESSED_W
617
618 return res;
619}
620//******************************************************************************
621//******************************************************************************
622BOOL OSLibDosGetFileAttributesEx(PSZ pszName,
623 ULONG ulDummy,
624 PVOID pBuffer)
625{
626 APIRET rc; /* API return code */
627 FILESTATUS3 fs3; /* file information structure */
628 LPWIN32_FILE_ATTRIBUTE_DATA lpFad = (LPWIN32_FILE_ATTRIBUTE_DATA) pBuffer;
629
630 // Note: we only handle standard "GetFileExInfoStandard" requests
631 rc = DosQueryPathInfo(pszName, /* query the file information */
632 FIL_STANDARD,
633 &fs3,
634 sizeof(fs3));
635 if (rc != NO_ERROR) /* check for errors */
636 return FALSE; /* raise error condition */
637
638 // convert structure
639 lpFad->dwFileAttributes = pm2WinFileAttributes(fs3.attrFile);
640 pmDateTimeToFileTime(&fs3.fdateCreation, &fs3.ftimeCreation, &lpFad->ftCreationTime);
641 pmDateTimeToFileTime(&fs3.fdateLastAccess, &fs3.ftimeLastAccess, &lpFad->ftLastAccessTime);
642 pmDateTimeToFileTime(&fs3.fdateLastWrite, &fs3.ftimeLastWrite, &lpFad->ftLastWriteTime);
643
644 /* @@@PH we might add Aurora support ...
645 lpFad->nFileSizeHigh = info.nFileSizeHigh;
646 */
647 lpFad->nFileSizeHigh = 0;
648 lpFad->nFileSizeLow = fs3.cbFile;
649
650 return TRUE;
651}
652//******************************************************************************
653DWORD WIN32API GetEnvironmentVariableA(LPCSTR, LPSTR, DWORD );
654//******************************************************************************
655DWORD OSLibDosSearchPath(DWORD cmd, char *path, char *name, char *full_name,
656 DWORD length_fullname)
657{
658 switch(cmd) {
659 case OSLIB_SEARCHDIR:
660 if(DosSearchPath(SEARCH_IGNORENETERRS, path,
661 name, full_name, length_fullname) != 0) {
662 return 0;
663 }
664 return strlen(full_name);
665
666
667 case OSLIB_SEARCHCURDIR:
668 if(DosSearchPath(SEARCH_IGNORENETERRS | SEARCH_CUR_DIRECTORY, path,
669 name, full_name, length_fullname) != 0) {
670 return 0;
671 }
672 return strlen(full_name);
673
674 case OSLIB_SEARCHFILE:
675 {
676 FILESTATUS3 fileinfo;
677
678 if(DosQueryPathInfo(name, FIL_STANDARD, &fileinfo, sizeof(fileinfo)) != 0) {
679 return 0;
680 }
681 strncpy(full_name, name, length_fullname);
682 full_name[length_fullname-1] = 0;
683 return strlen(full_name);
684 }
685
686 case OSLIB_SEARCHENV:
687 {
688 LPSTR envstring;
689 int envsize;
690 CHAR szResult[CCHMAXPATH];
691
692 envsize = GetEnvironmentVariableA(path, NULL, 0);
693 envstring = (LPSTR)malloc(envsize+1);
694 GetEnvironmentVariableA(path, envstring, envsize);
695 if(DosSearchPath(SEARCH_IGNORENETERRS, envstring,
696 name, szResult, sizeof(szResult)) != 0) {
697 free(envstring);
698 return 0;
699 }
700 free(envstring);
701 strcpy(full_name, szResult);
702 return strlen(full_name);
703 }
704 }
705 return 0;
706}
707//******************************************************************************
708//******************************************************************************
709DWORD OSLibDosQueryPathInfo(CHAR *pszPathName,
710 ULONG ulInfoLevel,
711 PVOID pInfoBuf,
712 ULONG cbInfoBuf)
713{
714 APIRET rc = DosQueryPathInfo( pszPathName, ulInfoLevel,
715 pInfoBuf, cbInfoBuf );
716
717 if(rc == ERROR_TOO_MANY_OPEN_FILES)
718 {
719 LONG reqCount = 2;
720 ULONG maxFiles;
721
722 if(DosSetRelMaxFH(&reqCount, &maxFiles) == NO_ERROR)
723 rc = DosQueryPathInfo(pszPathName, ulInfoLevel,
724 pInfoBuf, cbInfoBuf );
725 }
726 return rc;
727}
728//******************************************************************************
729//******************************************************************************
730DWORD OSLibDosCreateFile(CHAR *lpszFile,
731 DWORD fuAccess,
732 DWORD fuShare,
733 LPSECURITY_ATTRIBUTES lpSecurityAttributes,
734 DWORD fuCreate,
735 DWORD fuAttrFlags,
736 HANDLE hTemplateFile)
737{
738 HFILE hFile;
739 ULONG actionTaken = 0;
740 ULONG fileSize = 0;
741 ULONG fileAttr = FILE_NORMAL;
742 ULONG openFlag = 0;
743 ULONG openMode = 0;
744 APIRET rc = ERROR_NOT_ENOUGH_MEMORY;;
745
746 //TODO: lpSecurityAttributes (inheritance)
747
748 if(fuAttrFlags & FILE_ATTRIBUTE_ARCHIVE_W)
749 fileAttr |= FILE_ARCHIVED;
750 if(fuAttrFlags & FILE_ATTRIBUTE_HIDDEN_W)
751 fileAttr |= FILE_HIDDEN;
752 if(fuAttrFlags & FILE_ATTRIBUTE_SYSTEM_W)
753 fileAttr |= FILE_SYSTEM;
754 if(fuAttrFlags & FILE_ATTRIBUTE_READONLY_W)
755 fileAttr |= FILE_READONLY;
756 // TODO: FILE_ATTRIBUTE_TEMPORARY_W
757
758 switch(fuCreate)
759 {
760 case CREATE_NEW_W:
761 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_FAIL_IF_EXISTS;
762 break;
763 case CREATE_ALWAYS_W:
764 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS;
765 break;
766 case OPEN_EXISTING_W:
767 openFlag |= OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
768 break;
769 case OPEN_ALWAYS_W:
770 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
771 break;
772 case TRUNCATE_EXISTING_W:
773 openFlag |= OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS;
774 break;
775 }
776
777 if(fuAttrFlags & FILE_FLAG_WRITE_THROUGH_W) openMode |= OPEN_FLAGS_WRITE_THROUGH;
778 if(fuAttrFlags & FILE_FLAG_NO_BUFFERING_W) openMode |= OPEN_FLAGS_NO_CACHE;
779 if(fuAttrFlags & FILE_FLAG_RANDOM_ACCESS_W) openMode |= OPEN_FLAGS_RANDOM;
780 if(fuAttrFlags & FILE_FLAG_SEQUENTIAL_SCAN_W) openMode |= OPEN_FLAGS_SEQUENTIAL;
781 // TODO: FILE_FLAG_BACKUP_SEMANTICS_W
782 // FILE_FLAG_POSIX_SEMANTICS_W are not supported
783
784 //TODO: FILE_SHARE_DELETE
785 if((fuShare & (FILE_SHARE_READ_W | FILE_SHARE_WRITE_W)) == 0 )
786 openMode |= OPEN_SHARE_DENYREADWRITE;
787 else
788 if((fuShare & (FILE_SHARE_READ_W | FILE_SHARE_WRITE_W)) == (FILE_SHARE_READ_W | FILE_SHARE_WRITE_W))
789 openMode |= OPEN_SHARE_DENYNONE;
790 else
791 if(fuShare & FILE_SHARE_READ_W)
792 openMode |= OPEN_SHARE_DENYWRITE;
793 else
794 if(fuShare & FILE_SHARE_WRITE_W)
795 openMode |= OPEN_SHARE_DENYREAD;
796
797 if(fuAccess == (GENERIC_READ_W | GENERIC_WRITE_W))
798 openMode |= OPEN_ACCESS_READWRITE;
799 else
800 if(fuAccess & GENERIC_READ_W)
801 openMode |= OPEN_ACCESS_READONLY;
802 else
803 if(fuAccess & GENERIC_WRITE_W)
804 openMode |= OPEN_ACCESS_WRITEONLY;
805
806#if 0
807 //SvL: Not true; verified in NT! (also messed up access of files on
808 // readonly volumes)
809 // CreateFile with OPEN_ALWAYS & GENERIC_READ on non-existing file
810 // -> creates 0 size file, WriteFile is not allowed
811 // Same in OS/2.
812 /* if creating a file, access cannot be readonly! */
813 if (openFlag & OPEN_ACTION_CREATE_IF_NEW &&
814 (!(openMode & OPEN_ACCESS_READWRITE) &&
815 !(openMode & OPEN_ACCESS_WRITEONLY))) {
816 openMode |= OPEN_ACCESS_READWRITE;
817 }
818#endif
819
820 if(strlen(lpszFile) == 2 && lpszFile[1] == ':') {
821 //app tries to open physical disk
822 openMode |= OPEN_FLAGS_DASD;
823 }
824 int retry = 0;
825 while(retry < 2)
826 {
827 dprintf(("DosOpen %s openFlag=%x openMode=%x", lpszFile, openFlag, openMode));
828 rc = DosOpen((PSZ)lpszFile,
829 &hFile,
830 &actionTaken,
831 fileSize,
832 fileAttr,
833 openFlag,
834 openMode,
835 NULL);
836 if(rc == ERROR_TOO_MANY_OPEN_FILES)
837 {
838 ULONG CurMaxFH;
839 LONG ReqCount = 32;
840
841 rc = DosSetRelMaxFH(&ReqCount, &CurMaxFH);
842 if(rc) {
843 dprintf(("DosSetRelMaxFH returned %d", rc));
844 SetLastError(ERROR_TOO_MANY_OPEN_FILES_W);
845 return INVALID_HANDLE_VALUE_W;
846 }
847 dprintf(("DosOpen failed -> increased nr open files to %d", CurMaxFH));
848 }
849 else break;
850 retry++;
851 }
852
853 if(rc)
854 {
855 SetLastError(error2WinError(rc));
856 return INVALID_HANDLE_VALUE_W;
857 }
858 SetLastError(ERROR_SUCCESS_W);
859 return hFile;
860}
861//******************************************************************************
862//******************************************************************************
863DWORD OSLibDosOpenFile(CHAR *lpszFile, UINT fuMode)
864{
865 ULONG actionTaken = 0;
866 ULONG fileSize = 0;
867 ULONG fileAttr = FILE_NORMAL;
868 ULONG openFlag = 0;
869 ULONG openMode = 0;
870 APIRET rc = ERROR_NOT_ENOUGH_MEMORY;
871 HFILE hFile;
872
873 if(!(fuMode & (OF_CREATE_W | OF_READWRITE_W | OF_WRITE_W)))
874 {
875 openMode |= OPEN_ACCESS_READONLY;
876 openFlag |= OPEN_ACTION_OPEN_IF_EXISTS;
877 }
878 else
879 {
880 if(fuMode & OF_CREATE_W) {
881 openFlag |= OPEN_ACTION_CREATE_IF_NEW |
882 OPEN_ACTION_REPLACE_IF_EXISTS;
883 }
884 else openFlag |= OPEN_ACTION_OPEN_IF_EXISTS;
885
886 if(fuMode & OF_READWRITE_W)
887 openMode |= OPEN_ACCESS_READWRITE;
888 else
889 if(fuMode & OF_WRITE_W)
890 openMode |= OPEN_ACCESS_WRITEONLY;
891 else
892 if(fuMode & OF_CREATE_W)
893 openMode |= OPEN_ACCESS_READWRITE;
894 }
895
896 if((fuMode & OF_SHARE_DENY_WRITE_W) ||
897 !(fuMode & (OF_SHARE_DENY_READ_W | OF_SHARE_DENY_NONE_W | OF_SHARE_EXCLUSIVE_W)))
898 openMode |= OPEN_SHARE_DENYWRITE;
899 else
900 if (fuMode & OF_SHARE_DENY_NONE_W)
901 openMode |= OPEN_SHARE_DENYNONE;
902 else
903 if (fuMode & OF_SHARE_DENY_READ_W)
904 openMode |= OPEN_SHARE_DENYREAD;
905 else
906 if (fuMode & OF_SHARE_EXCLUSIVE_W)
907 openMode |= OPEN_SHARE_DENYREADWRITE;
908
909 rc = DosOpen((PSZ)lpszFile,
910 &hFile,
911 &actionTaken,
912 fileSize,
913 fileAttr,
914 openFlag,
915 openMode,
916 NULL);
917
918 if(rc != NO_ERROR)
919 {
920 if(fuMode & OF_EXIST_W)
921 {
922 if(rc == ERROR_OPEN_FAILED || rc == ERROR_FILE_NOT_FOUND)
923 {
924 SetLastError(ERROR_FILE_NOT_FOUND_W);
925 return HFILE_ERROR_W;
926 }
927 }
928 if((rc == ERROR_OPEN_FAILED) && (openFlag & OPEN_ACTION_OPEN_IF_EXISTS))
929 {
930 SetLastError(ERROR_FILE_NOT_FOUND_W);
931 }
932 else SetLastError(error2WinError(rc));
933
934 return HFILE_ERROR_W;
935 }
936 SetLastError(ERROR_SUCCESS_W);
937 return hFile;
938}
939//******************************************************************************
940//******************************************************************************
941BOOL OSLibDosLockFile(DWORD hFile, DWORD dwFlags,
942 DWORD OffsetLow, DWORD OffsetHigh,
943 DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh,
944 LPOVERLAPPED lpOverlapped)
945{
946 APIRET rc;
947
948 // Set 5 secs timeout for locking file and no other can access this
949 // file region
950
951 if(lpOverlapped) {//TODO:
952 dprintf(("OSLibDosLockFile: overlapped lock not yet implemented!!"));
953 }
954 //TODO: Locking region crossing end of file is permitted. Works in OS/2??
955 if(f64BitIO)
956 {
957 FILELOCKL lockRangeL;
958
959 lockRangeL.lOffset.ulLo = OffsetLow;
960 lockRangeL.lOffset.ulHi = OffsetHigh;
961 lockRangeL.lRange.ulLo = nNumberOfBytesToLockLow;
962 lockRangeL.lRange.ulHi = nNumberOfBytesToLockHigh;
963
964 rc = OdinDosSetFileLocksL(hFile, NULL, &lockRangeL,
965 (dwFlags & LOCKFILE_FAIL_IMMEDIATELY_W) ? 0 : 5000, 0);
966 //SvL: 64 bits values are only supported by JFS
967 // Try the 32 bits DosSetFileLocks if it fails
968 // (TODO: should check the partition type instead)
969 if(rc == ERROR_INVALID_PARAMETER && (OffsetHigh || nNumberOfBytesToLockHigh)) {
970 goto oldlock;
971 }
972 }
973 else
974 {
975oldlock:
976 FILELOCK lockRange = { OffsetLow, nNumberOfBytesToLockLow };
977
978 rc = DosSetFileLocks(hFile, NULL, &lockRange,
979 (dwFlags & LOCKFILE_FAIL_IMMEDIATELY_W) ? 0 : 5000, 0);
980 }
981 if(rc) {
982 SetLastError(error2WinError(rc));
983 return FALSE;
984 }
985 SetLastError(ERROR_SUCCESS_W);
986 return TRUE;
987}
988//******************************************************************************
989//******************************************************************************
990BOOL OSLibDosUnlockFile(DWORD hFile, DWORD OffsetLow, DWORD OffsetHigh,
991 DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh,
992 LPOVERLAPPED lpOverlapped)
993{
994 APIRET rc;
995
996 // Set 5 secs timeout for unlocking file and no other can access this
997 // file region
998
999 if(lpOverlapped) {//TODO:
1000 dprintf(("OSLibDosUnlockFile: overlapped unlock not yet implemented!!"));
1001 }
1002 if(f64BitIO)
1003 {
1004 FILELOCKL unlockRangeL;
1005
1006 unlockRangeL.lOffset.ulLo = OffsetLow;
1007 unlockRangeL.lOffset.ulHi = OffsetHigh;
1008 unlockRangeL.lRange.ulLo = nNumberOfBytesToLockLow;
1009 unlockRangeL.lRange.ulHi = nNumberOfBytesToLockHigh;
1010
1011 rc = OdinDosSetFileLocksL(hFile, &unlockRangeL, NULL, 5000, 0);
1012 //SvL: 64 bits values are only supported by JFS
1013 // Try the 32 bits DosSetFileLocks if it fails
1014 // (TODO: should check the partition type instead)
1015 if(rc == ERROR_INVALID_PARAMETER && (OffsetHigh || nNumberOfBytesToLockHigh)) {
1016 goto oldlock;
1017 }
1018 }
1019 else
1020 {
1021oldlock:
1022 FILELOCK unlockRange = { OffsetLow, nNumberOfBytesToLockLow };
1023
1024 rc = DosSetFileLocks(hFile, &unlockRange, NULL, 5000, 0);
1025 }
1026 if(rc) {
1027 SetLastError(error2WinError(rc));
1028 return FALSE;
1029 }
1030 SetLastError(ERROR_SUCCESS_W);
1031 return TRUE;
1032}
1033//******************************************************************************
1034//******************************************************************************
1035BOOL OSLibDosFlushFileBuffers(DWORD hFile)
1036{
1037 APIRET rc;
1038
1039 rc = DosResetBuffer(hFile);
1040 SetLastError(error2WinError(rc));
1041 return (rc == NO_ERROR);
1042}
1043//******************************************************************************
1044//******************************************************************************
1045DWORD OSLibDosGetFileSize(DWORD hFile, LPDWORD lpdwFileSizeHigh)
1046{
1047 APIRET rc;
1048 ULONG sizeLow;
1049
1050 if(f64BitIO)
1051 {
1052 FILESTATUS3L fsts3ConfigInfoL = {{0}};
1053 ULONG ulBufSize = sizeof(FILESTATUS3L);
1054
1055 rc = DosQueryFileInfo(hFile, FIL_STANDARDL, &fsts3ConfigInfoL, ulBufSize);
1056 if(lpdwFileSizeHigh) {
1057 *lpdwFileSizeHigh = fsts3ConfigInfoL.cbFile.ulHi;
1058 }
1059 sizeLow = fsts3ConfigInfoL.cbFile.ulLo;
1060 }
1061 else
1062 {
1063 FILESTATUS3 fsts3ConfigInfo = {{0}};
1064 ULONG ulBufSize = sizeof(FILESTATUS3);
1065
1066 if(lpdwFileSizeHigh) {
1067 *lpdwFileSizeHigh = 0;
1068 }
1069 rc = DosQueryFileInfo(hFile, FIL_STANDARD, &fsts3ConfigInfo, ulBufSize);
1070 sizeLow = fsts3ConfigInfo.cbFile;
1071 }
1072 if(rc) {
1073 SetLastError(error2WinError(rc));
1074 return -1;
1075 }
1076 SetLastError(ERROR_SUCCESS_W);
1077 return sizeLow;
1078}
1079//******************************************************************************
1080//******************************************************************************
1081DWORD OSLibDosSetFilePointer(DWORD hFile, DWORD OffsetLow, DWORD *OffsetHigh, DWORD method)
1082{
1083 LONGLONG offsetL;
1084 LONGLONG newoffsetL;
1085 APIRET rc;
1086 DWORD newoffset;
1087
1088 switch(method)
1089 {
1090 case FILE_BEGIN_W:
1091 method = FILE_BEGIN;
1092 break;
1093
1094 case FILE_CURRENT_W:
1095 method = FILE_CURRENT;
1096 break;
1097
1098 case FILE_END_W:
1099 method = FILE_END;
1100 break;
1101 }
1102
1103 // PH Note: for a negative 32-bit seek, the OS/2 64-bit version
1104 // needs to be skipped.
1105 if( (f64BitIO) && (OffsetHigh) )
1106 {
1107 offsetL.ulLo = OffsetLow;
1108 offsetL.ulHi = (OffsetHigh) ? *OffsetHigh : 0;
1109 rc = OdinDosSetFilePtrL(hFile, offsetL, method, &newoffsetL);
1110 if(OffsetHigh) {
1111 *OffsetHigh = newoffsetL.ulHi;
1112 }
1113 newoffset = newoffsetL.ulLo;
1114 }
1115 else rc = DosSetFilePtr(hFile, OffsetLow, method, &newoffset);
1116
1117 if(rc)
1118 {
1119 SetLastError(error2WinError(rc));
1120 return -1;
1121 }
1122 SetLastError(ERROR_SUCCESS_W);
1123 return newoffset;
1124}
1125//******************************************************************************
1126//******************************************************************************
1127BOOL OSLibDosSetEndOfFile(DWORD hFile)
1128{
1129 ULONG newFilePos;
1130 LONGLONG FilePosL = {0,0};
1131 LONGLONG newFilePosL;
1132 APIRET rc;
1133
1134 if(f64BitIO) {
1135 rc = OdinDosSetFilePtrL(hFile, FilePosL, FILE_CURRENT, &newFilePosL);
1136 if(rc == 0) {
1137 rc = OdinDosSetFileSizeL(hFile, newFilePosL);
1138 }
1139 }
1140 else {
1141 rc = DosSetFilePtr(hFile, 0, FILE_CURRENT, &newFilePos);
1142 if(rc == 0) {
1143 rc = DosSetFileSize(hFile, newFilePos);
1144 }
1145 }
1146 if(rc) {
1147 SetLastError(error2WinError(rc));
1148 return FALSE;
1149 }
1150 SetLastError(ERROR_SUCCESS_W);
1151 return TRUE;
1152}
1153//******************************************************************************
1154//******************************************************************************
1155BOOL OSLibDosGetFileInformationByHandle(DWORD hFile, BY_HANDLE_FILE_INFORMATION* pInfo)
1156{
1157 APIRET rc;
1158
1159 if(f64BitIO)
1160 {
1161 FILESTATUS4L statusL = { 0 };
1162
1163 rc = DosQueryFileInfo(hFile, FIL_QUERYEASIZEL,
1164 &statusL, sizeof(statusL));
1165 if(rc == NO_ERROR)
1166 {
1167 pInfo->dwFileAttributes = 0;
1168 if(!(statusL.attrFile & NOT_NORMAL))
1169 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_NORMAL_W;
1170 if(statusL.attrFile & FILE_READONLY)
1171 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_READONLY_W;
1172 if(statusL.attrFile & FILE_HIDDEN)
1173 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN_W;
1174 if(statusL.attrFile & FILE_SYSTEM)
1175 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_SYSTEM_W;
1176 if(statusL.attrFile & FILE_DIRECTORY)
1177 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY_W;
1178 if(statusL.attrFile & FILE_ARCHIVED)
1179 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_ARCHIVE_W;
1180
1181 pmDateTimeToFileTime(&statusL.fdateCreation,
1182 &statusL.ftimeCreation,
1183 &pInfo->ftCreationTime);
1184 pmDateTimeToFileTime(&statusL.fdateLastAccess,
1185 &statusL.ftimeLastAccess,
1186 &pInfo->ftLastAccessTime);
1187 pmDateTimeToFileTime(&statusL.fdateLastWrite,
1188 &statusL.ftimeLastWrite,
1189 &pInfo->ftLastWriteTime);
1190
1191 pInfo->nFileSizeHigh = statusL.cbFile.ulHi;
1192 pInfo->nFileSizeLow = statusL.cbFile.ulLo;
1193 pInfo->dwVolumeSerialNumber = 0; //todo
1194 pInfo->nNumberOfLinks = 1;
1195 pInfo->nFileIndexHigh = 0;
1196 pInfo->nFileIndexLow = 0;
1197 }
1198 }
1199 else
1200 {
1201 FILESTATUS4 status = { 0 };
1202
1203 rc = DosQueryFileInfo(hFile, FIL_QUERYEASIZE, &status,
1204 sizeof(status));
1205 if(rc == NO_ERROR)
1206 {
1207 pInfo->dwFileAttributes = 0;
1208 if(!(status.attrFile & NOT_NORMAL))
1209 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_NORMAL_W;
1210 if(status.attrFile & FILE_READONLY)
1211 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_READONLY_W;
1212 if(status.attrFile & FILE_HIDDEN)
1213 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN_W;
1214 if(status.attrFile & FILE_SYSTEM)
1215 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_SYSTEM_W;
1216 if(status.attrFile & FILE_DIRECTORY)
1217 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY_W;
1218 if(status.attrFile & FILE_ARCHIVED)
1219 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_ARCHIVE_W;
1220
1221 pmDateTimeToFileTime(&status.fdateCreation,
1222 &status.ftimeCreation,
1223 &pInfo->ftCreationTime);
1224 pmDateTimeToFileTime(&status.fdateLastAccess,
1225 &status.ftimeLastAccess,
1226 &pInfo->ftLastAccessTime);
1227 pmDateTimeToFileTime(&status.fdateLastWrite,
1228 &status.ftimeLastWrite,
1229 &pInfo->ftLastWriteTime);
1230
1231 pInfo->nFileSizeHigh = 0;
1232 pInfo->nFileSizeLow = status.cbFile;
1233 pInfo->dwVolumeSerialNumber = 0; //todo
1234 pInfo->nNumberOfLinks = 1;
1235 pInfo->nFileIndexHigh = 0;
1236 pInfo->nFileIndexLow = 0;
1237 }
1238 }
1239 if(rc) {
1240 SetLastError(error2WinError(rc));
1241 return FALSE;
1242 }
1243 SetLastError(ERROR_SUCCESS_W);
1244 return TRUE;
1245}
1246//******************************************************************************
1247//******************************************************************************
1248BOOL OSLibDosSetFileTime(DWORD hFile, WORD creationdate, WORD creationtime,
1249 WORD lastaccessdate, WORD lastaccesstime,
1250 WORD lastwritedate, WORD lastwritetime)
1251{
1252 FILESTATUS3 fileInfo;
1253 APIRET rc;
1254
1255 rc = DosQueryFileInfo(hFile, FIL_STANDARD, &fileInfo, sizeof(fileInfo));
1256
1257 if(rc == NO_ERROR)
1258 {
1259 if(creationdate && creationtime) {
1260 fileInfo.fdateCreation = *(FDATE *)&creationdate;
1261 fileInfo.ftimeCreation = *(FTIME *)&creationtime;
1262 }
1263 if(lastaccessdate && lastaccesstime) {
1264 fileInfo.fdateLastAccess = *(FDATE *)&lastaccessdate;
1265 fileInfo.ftimeLastAccess = *(FTIME *)&lastaccesstime;
1266 }
1267 if(lastwritedate && lastwritetime) {
1268 fileInfo.fdateLastWrite = *(FDATE *)&lastwritedate;
1269 fileInfo.ftimeLastWrite = *(FTIME *)&lastwritetime;
1270 }
1271
1272 rc = DosSetFileInfo(hFile, FIL_STANDARD, &fileInfo, sizeof(fileInfo));
1273 }
1274
1275 if(rc)
1276 {
1277 SetLastError(error2WinError(rc));
1278 return FALSE;
1279 }
1280 SetLastError(ERROR_SUCCESS_W);
1281 return TRUE;
1282}
1283//******************************************************************************
1284//******************************************************************************
1285BOOL OSLibDosGetFileTime(DWORD hFile, WORD *creationdate, WORD *creationtime,
1286 WORD *lastaccessdate, WORD *lastaccesstime,
1287 WORD *lastwritedate, WORD *lastwritetime)
1288{
1289 FILESTATUS3 fileInfo;
1290 APIRET rc;
1291
1292 rc = DosQueryFileInfo(hFile, FIL_STANDARD, &fileInfo, sizeof(fileInfo));
1293
1294 if(rc == NO_ERROR)
1295 {
1296 *creationdate = *(WORD *)&fileInfo.fdateCreation;
1297 *creationtime = *(WORD *)&fileInfo.ftimeCreation;
1298 *lastaccessdate = *(WORD *)&fileInfo.fdateLastAccess;
1299 *lastaccesstime = *(WORD *)&fileInfo.ftimeLastAccess;
1300 *lastwritedate = *(WORD *)&fileInfo.fdateLastWrite;
1301 *lastwritetime = *(WORD *)&fileInfo.ftimeLastWrite;
1302 }
1303
1304 if(rc)
1305 {
1306 SetLastError(error2WinError(rc));
1307 return FALSE;
1308 }
1309 SetLastError(ERROR_SUCCESS_W);
1310 return TRUE;
1311}
1312//******************************************************************************
1313//******************************************************************************
1314DWORD OSLibDosSetFilePtr2(DWORD hFile, DWORD offset, DWORD method)
1315{
1316 DWORD newoffset;
1317 APIRET rc;
1318
1319
1320 rc = DosSetFilePtr(hFile, offset, method, &newoffset);
1321 if(rc) {
1322 dprintf(("DosSetFilePtr Error rc:%d", rc));
1323 return -1;
1324 }
1325 else return newoffset;
1326}
1327//******************************************************************************
1328//******************************************************************************
1329DWORD OSLibDosDupHandle(DWORD hFile, DWORD *hNew)
1330{
1331 *hNew = -1;
1332 return DosDupHandle(hFile, hNew);
1333}
1334//******************************************************************************
1335//******************************************************************************
1336void OSLibDosDisableHardError(BOOL fTurnOff)
1337{
1338 DosError((fTurnOff) ? FERR_DISABLEHARDERR : FERR_ENABLEHARDERR);
1339}
1340//******************************************************************************
1341//Returns time spent in kernel & user mode in milliseconds
1342//******************************************************************************
1343BOOL OSLibDosQueryProcTimes(DWORD procid, ULONG *kerneltime, ULONG *usertime)
1344{
1345 APIRET rc;
1346 char *buf;
1347 ULONG size;
1348 ULONG nrthreads = 4;
1349
1350tryagain:
1351 size = sizeof(QTOPLEVEL)+sizeof(QGLOBAL)+sizeof(QPROCESS) + nrthreads*sizeof(QTHREAD);
1352 buf = (char *)malloc(size);
1353 rc = DosQuerySysState(0x1, RESERVED, procid, RESERVED, (PCHAR)buf, size);
1354
1355 if(rc) {
1356 free(buf);
1357 if(rc == ERROR_BUFFER_OVERFLOW) {
1358 nrthreads += 4;
1359 goto tryagain;
1360 }
1361 return FALSE;
1362 }
1363 PQTOPLEVEL top = (PQTOPLEVEL)buf;
1364
1365 *kerneltime = 0;
1366 *usertime = 0;
1367 for(int i=0;i<top->procdata->threadcnt;i++) {
1368 *kerneltime += top->procdata->threads[i].systime;
1369 *usertime += top->procdata->threads[i].usertime;
1370 }
1371 free(buf);
1372 return TRUE;
1373}
1374//******************************************************************************
1375//******************************************************************************
1376// TODO: implement SecurityAttributes parameter
1377DWORD OSLibDosCreateNamedPipe(LPCTSTR lpName,
1378 DWORD dwOpenMode,
1379 DWORD dwPipeMode,
1380 DWORD nMaxInstances,
1381 DWORD nOutBufferSize,
1382 DWORD nInBufferSize,
1383 DWORD nDefaultTimeOut,
1384 LPSECURITY_ATTRIBUTES lpSecurityAttributes)
1385{ DWORD dwOS2Mode = 0;
1386 DWORD dwOS2PipeMode = 0;
1387 LPSTR lpOS2Name;
1388 DWORD hPipe;
1389 DWORD rc;
1390
1391 if (dwOpenMode & PIPE_ACCESS_DUPLEX_W)
1392 dwOS2Mode |= NP_ACCESS_DUPLEX;
1393 else
1394 if (dwOpenMode & PIPE_ACCESS_INBOUND_W)
1395 dwOS2Mode |= NP_ACCESS_INBOUND;
1396 else
1397 if (dwOpenMode & PIPE_ACCESS_OUTBOUND_W)
1398 dwOS2Mode |= NP_ACCESS_OUTBOUND;
1399 // TODO:
1400 // if(dwOpenMode & FILE_FLAG_OVERLAPPED)
1401 // if(dwOpenMode & WRITE_DAC)
1402 // if(dwOpenMode & WRITE_OWNER)
1403 // if(dwOpenMode & ACCESS_SYSTEM_SECURITY)
1404 if(dwOpenMode & FILE_FLAG_WRITE_THROUGH_W)
1405 dwOS2Mode |= NP_WRITEBEHIND; // FIXME: I'm not sure!
1406
1407 if (dwPipeMode & PIPE_WAIT_W)
1408 dwOS2PipeMode |= NP_WAIT;
1409 if (dwPipeMode & PIPE_NOWAIT_W)
1410 dwOS2PipeMode |= NP_NOWAIT;
1411 if (dwPipeMode & PIPE_READMODE_BYTE_W)
1412 dwOS2PipeMode |= NP_READMODE_BYTE;
1413 if (dwPipeMode & PIPE_READMODE_MESSAGE_W)
1414 dwOS2PipeMode |= NP_READMODE_MESSAGE;
1415 if (dwPipeMode & PIPE_TYPE_BYTE_W)
1416 dwOS2PipeMode |= NP_TYPE_BYTE;
1417 if (dwPipeMode & PIPE_TYPE_MESSAGE_W)
1418 dwOS2PipeMode |= NP_TYPE_MESSAGE;
1419
1420 if (nMaxInstances>0xff)
1421 {
1422 SetLastError(ERROR_INVALID_PARAMETER_W); // ERROR_INVALID_PARAMETER
1423 return -1; // INVALID_HANDLE_VALUE
1424 }
1425 dwOS2PipeMode |= nMaxInstances;
1426
1427 if (strstr(lpName,"\\\\."))
1428 {
1429 // If pipe is created on the local machine
1430 // we must delete string \\. because
1431 // in Windows named pipes scheme is a \\.\PIPE\pipename
1432 // but in OS/2 only \PIPE\pipename
1433 lpOS2Name = (LPSTR)lpName + 3;
1434 }
1435 else lpOS2Name = (LPSTR)lpName;
1436
1437 dprintf(("DosCreateNPipe(%s,%x,%x,%x,%x,%x)",lpOS2Name,dwOS2Mode,dwOS2PipeMode,nInBufferSize,nOutBufferSize,nDefaultTimeOut));
1438 rc=DosCreateNPipe(lpOS2Name,
1439 &hPipe,
1440 dwOS2Mode,
1441 dwOS2PipeMode,
1442 nInBufferSize,
1443 nInBufferSize,
1444 nDefaultTimeOut); // Timeouts must be tested!
1445
1446 dprintf(("DosCreateNPipe rc=%d",rc));
1447 if (rc)
1448 {
1449 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER_W));
1450 return -1; // INVALID_HANDLE_VALUE
1451 }
1452 return hPipe;
1453}
1454
1455//******************************************************************************
1456//******************************************************************************
1457// TODO: implement lpOverlapped parameter!
1458BOOL OSLibDosConnectNamedPipe(DWORD hNamedPipe, LPOVERLAPPED lpOverlapped)
1459{
1460 DWORD rc;
1461
1462 rc=DosConnectNPipe(hNamedPipe);
1463 dprintf(("DosConnectNPipe rc=%d",rc));
1464
1465 if (!rc) return (TRUE);
1466 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1467
1468 return (FALSE);
1469}
1470
1471//******************************************************************************
1472//******************************************************************************
1473BOOL OSLibDosCallNamedPipe( LPCTSTR lpNamedPipeName,
1474 LPVOID lpInBuffer,
1475 DWORD nInBufferSize,
1476 LPVOID lpOutBuffer,
1477 DWORD nOutBufferSize,
1478 LPDWORD lpBytesRead,
1479 DWORD nTimeOut )
1480{
1481 LPSTR lpOS2Name;
1482 DWORD rc;
1483
1484 if (strstr(lpNamedPipeName,"\\\\."))
1485 {
1486 // If pipe is created on the local machine
1487 // we must delete string \\. because
1488 // in Windows named pipes scheme is a \\.\PIPE\pipename
1489 // but in OS/2 only \PIPE\pipename
1490 lpOS2Name = (LPSTR)lpNamedPipeName + 3;
1491 }
1492 else lpOS2Name = (LPSTR)lpNamedPipeName;
1493
1494 rc=DosCallNPipe(lpOS2Name,
1495 lpInBuffer,
1496 nInBufferSize,
1497 lpOutBuffer,
1498 nOutBufferSize,
1499 lpBytesRead,
1500 nTimeOut );
1501
1502
1503 if (!rc) return (TRUE);
1504 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1505
1506 return (FALSE);
1507}
1508
1509//******************************************************************************
1510//******************************************************************************
1511BOOL OSLibDosTransactNamedPipe( DWORD hNamedPipe,
1512 LPVOID lpInBuffer,
1513 DWORD nInBufferSize,
1514 LPVOID lpOutBuffer,
1515 DWORD nOutBufferSize,
1516 LPDWORD lpBytesRead,
1517 LPOVERLAPPED lpOverlapped)
1518{
1519 DWORD rc;
1520
1521 rc=DosTransactNPipe(hNamedPipe,
1522 lpOutBuffer,
1523 nOutBufferSize,
1524 lpInBuffer,
1525 nInBufferSize,
1526 lpBytesRead);
1527
1528 dprintf(("DosTransactNPipe returned rc=%d");)
1529 if (!rc) return (TRUE);
1530 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1531
1532 return (FALSE);
1533}
1534
1535//******************************************************************************
1536//******************************************************************************
1537BOOL OSLibDosPeekNamedPipe(DWORD hPipe,
1538 LPVOID lpvBuffer,
1539 DWORD cbBuffer,
1540 LPDWORD lpcbRead,
1541 LPDWORD lpcbAvail,
1542 LPDWORD lpcbMessage)
1543{
1544 DWORD rc;
1545 AVAILDATA availData ={0};
1546 ULONG ulDummy;
1547
1548 rc=DosPeekNPipe(hPipe,lpvBuffer,cbBuffer,lpcbRead,&availData,&ulDummy);
1549
1550 dprintf(("DosPeekNPipe returned rc=%d",rc));
1551
1552 if (!rc)
1553 {
1554 *lpcbAvail = availData.cbpipe;
1555 *lpcbMessage = availData.cbmessage;
1556 return (TRUE);
1557 }
1558 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1559
1560 return (FALSE);
1561}
1562//******************************************************************************
1563//******************************************************************************
1564BOOL OSLibDosDisconnectNamedPipe(DWORD hPipe)
1565{
1566 DWORD rc;
1567
1568 rc=DosDisConnectNPipe(hPipe);
1569
1570 dprintf(("DosDisConnectNPipe returned rc=%d",rc));
1571
1572 if (!rc) return TRUE;
1573 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1574
1575 return (FALSE);
1576}
1577//******************************************************************************
1578//******************************************************************************
1579BOOL OSLibDosWaitNamedPipe(LPCSTR lpszNamedPipeName,
1580 DWORD dwTimeout)
1581{
1582 LPSTR lpOS2Name;
1583 DWORD rc;
1584
1585 if (strstr(lpszNamedPipeName,"\\\\."))
1586 {
1587 // If pipe is created on the local machine
1588 // we must delete string \\. because
1589 // in Windows named pipes scheme is a \\.\PIPE\pipename
1590 // but in OS/2 only \PIPE\pipename
1591 lpOS2Name = (LPSTR)lpszNamedPipeName + 3;
1592 }
1593 else lpOS2Name = (LPSTR)lpszNamedPipeName;
1594
1595 rc=DosWaitNPipe(lpOS2Name,dwTimeout);
1596
1597 dprintf(("DosWaitNPipe returned rc=%d",rc));
1598
1599 if (!rc) return TRUE;
1600 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1601
1602 return (FALSE);
1603}
1604//******************************************************************************
1605//******************************************************************************
1606BOOL isRoot(CHAR* name)
1607{
1608 if (name[1] == ':')
1609 {
1610 //local name (x:\)
1611 return (name[2] == 0) || !strchr(&name[3],'\\');
1612 } else if (name[0] == '\\')
1613 {
1614 //UNC name (\\resource\drive\)
1615 CHAR *drive,*dir;
1616
1617 drive = strchr(&name[2],'\\');
1618 if (!drive) return FALSE;
1619 dir = strchr(&drive[1],'\\');
1620 if (!dir) return TRUE;
1621 return !strchr(&dir[1],'\\');
1622 } else return FALSE; //unknown
1623}
1624//******************************************************************************
1625//******************************************************************************
1626inline CHAR system2DOSCharacter(CHAR ch)
1627{
1628 switch(ch)
1629 {
1630 case ' ':
1631 case '.':
1632 case '~':
1633 return '_';
1634
1635 default:
1636 return toupper(ch);
1637 }
1638}
1639
1640VOID long2ShortName(CHAR* longName,CHAR* shortName)
1641{
1642 INT x;
1643 CHAR *source = longName,*dest = shortName,*ext = strrchr(longName,'.');
1644
1645 if ((strcmp(longName,".") == 0) || (strcmp(longName,"..") == 0))
1646 {
1647 strcpy(shortName,longName);
1648 return;
1649 }
1650
1651 //CB: quick and dirty, real FILE~12.EXT is too slow
1652
1653 //8 character file name
1654 for (x = 0;x < 8;x++)
1655 {
1656 if ((source == ext) || (source[0] == 0)) break;
1657 dest[0] = system2DOSCharacter(source[0]);
1658 source++;
1659 dest++;
1660 }
1661
1662 if (source[0] == 0)
1663 {
1664 dest[0] = 0;
1665 return;
1666 }
1667
1668 if (source != ext)
1669 {
1670 //longName > 8 characters, insert ~1
1671 shortName[6] = '~';
1672 shortName[7] = '1';
1673 }
1674
1675 if (ext)
1676 {
1677 //add extension, 3 characters
1678 dest[0] = ext[0];
1679 dest++;
1680 ext++;
1681 for (x = 0;x < 3;x++)
1682 {
1683 if (ext[0] == 0) break;
1684 dest[0] = system2DOSCharacter(ext[0]);
1685 ext++;
1686 dest++;
1687 }
1688 }
1689 dest[0] = 0;
1690}
1691//******************************************************************************
1692//******************************************************************************
1693VOID translateFileResults(FILESTATUS3 *pResult,LPWIN32_FIND_DATAA pFind,CHAR* achName)
1694{
1695 CHAR* name;
1696
1697 pFind->dwFileAttributes = pm2WinFileAttributes(pResult->attrFile);
1698
1699 pmDateTimeToFileTime(&pResult->fdateCreation,&pResult->ftimeCreation,&pFind->ftCreationTime);
1700 pmDateTimeToFileTime(&pResult->fdateLastAccess,&pResult->ftimeLastAccess,&pFind->ftLastAccessTime);
1701 pmDateTimeToFileTime(&pResult->fdateLastWrite,&pResult->ftimeLastWrite,&pFind->ftLastWriteTime);
1702
1703 pFind->nFileSizeHigh = 0; //CB: fixme
1704 pFind->nFileSizeLow = pResult->cbFile;
1705 name = strrchr(achName,'\\');
1706 if (name)
1707 {
1708 name++;
1709 strcpy(pFind->cFileName,name);
1710 } else pFind->cFileName[0] = 0;
1711 long2ShortName(pFind->cFileName,pFind->cAlternateFileName);
1712}
1713
1714VOID translateFindResults(FILEFINDBUF3 *pResult,LPWIN32_FIND_DATAA pFind)
1715{
1716 pFind->dwFileAttributes = pm2WinFileAttributes(pResult->attrFile);
1717
1718 pmDateTimeToFileTime(&pResult->fdateCreation,&pResult->ftimeCreation,&pFind->ftCreationTime);
1719 pmDateTimeToFileTime(&pResult->fdateLastAccess,&pResult->ftimeLastAccess,&pFind->ftLastAccessTime);
1720 pmDateTimeToFileTime(&pResult->fdateLastWrite,&pResult->ftimeLastWrite,&pFind->ftLastWriteTime);
1721
1722 pFind->nFileSizeHigh = 0; //CB: fixme
1723 pFind->nFileSizeLow = pResult->cbFile;
1724 strcpy(pFind->cFileName,pResult->achName);
1725 long2ShortName(pFind->cFileName,pFind->cAlternateFileName);
1726}
1727//******************************************************************************
1728//******************************************************************************
1729DWORD OSLibDosFindFirst(LPCSTR lpFileName,WIN32_FIND_DATAA* lpFindFileData)
1730{
1731 HDIR hDir = -1;
1732 ULONG attrs;
1733 FILEFINDBUF3 result;
1734 ULONG searchCount = 1;
1735
1736 attrs = FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY | FILE_ARCHIVED;
1737 result.achName[0] = 0;
1738
1739 DosError(FERR_DISABLEHARDERR | FERR_DISABLEEXCEPTION);
1740 APIRET rc = DosFindFirst((PSZ)lpFileName,&hDir,attrs,&result,sizeof(result),&searchCount,FIL_STANDARD);
1741 DosError(FERR_ENABLEHARDERR | FERR_ENABLEEXCEPTION);
1742
1743 //check root: skip "." and ".." (HPFS, not on FAT)
1744 //check in OSLibDosFindNext not necessary: "." and ".." are the first two entries
1745 if ((rc == 0) && isRoot((LPSTR)lpFileName))
1746 {
1747 while ((strcmp(result.achName,".") == 0) || (strcmp(result.achName,"..") == 0))
1748 {
1749 result.achName[0] = 0;
1750 DosError(FERR_DISABLEHARDERR | FERR_DISABLEEXCEPTION);
1751 searchCount = 1;
1752 APIRET rc = DosFindNext(hDir,&result,sizeof(result),&searchCount);
1753 DosError(FERR_ENABLEHARDERR | FERR_ENABLEEXCEPTION);
1754 if (rc)
1755 {
1756 DosFindClose(hDir);
1757 SetLastError(error2WinError(rc));
1758
1759 return INVALID_HANDLE_VALUE_W;
1760 }
1761 }
1762 }
1763 if(rc) {
1764 DosFindClose(hDir);
1765 SetLastError(error2WinError(rc));
1766 return INVALID_HANDLE_VALUE_W;
1767 }
1768 translateFindResults(&result,lpFindFileData);
1769 SetLastError(ERROR_SUCCESS_W);
1770 return hDir;
1771}
1772//******************************************************************************
1773// NOTE: returns "." and ".." in root
1774//******************************************************************************
1775DWORD OSLibDosFindFirstMulti(LPCSTR lpFileName,WIN32_FIND_DATAA *lpFindFileData,DWORD *count)
1776{
1777 HDIR hDir = -1;
1778 ULONG attrs;
1779 FILEFINDBUF3 *result,*data;
1780 ULONG searchCount = *count;
1781
1782 attrs = FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY | FILE_ARCHIVED;
1783 result = (FILEFINDBUF3*)malloc(searchCount*sizeof(FILEFINDBUF3));
1784
1785 DosError(FERR_DISABLEHARDERR | FERR_DISABLEEXCEPTION);
1786 APIRET rc = DosFindFirst((PSZ)lpFileName,&hDir,attrs,result,searchCount*sizeof(FILEFINDBUF3),&searchCount,FIL_STANDARD);
1787 DosError(FERR_ENABLEHARDERR | FERR_ENABLEEXCEPTION);
1788 if (rc)
1789 {
1790 free(result);
1791 *count = 0;
1792 SetLastError(error2WinError(rc));
1793
1794 return INVALID_HANDLE_VALUE_W;
1795 }
1796
1797 data = result;
1798 for (int x = 0;x < searchCount;x++)
1799 {
1800 translateFindResults(data,&lpFindFileData[x]);
1801 data = (FILEFINDBUF3*)(((DWORD)data)+data->oNextEntryOffset);
1802 }
1803 free(result);
1804 *count = searchCount;
1805
1806 SetLastError(ERROR_SUCCESS_W);
1807 return hDir;
1808}
1809//******************************************************************************
1810//******************************************************************************
1811BOOL OSLibDosFindNext(DWORD hFindFile,WIN32_FIND_DATAA *lpFindFileData)
1812{
1813 FILEFINDBUF3 result;
1814 ULONG searchCount = 1;
1815
1816 APIRET rc = DosFindNext((HDIR)hFindFile,&result,sizeof(result),&searchCount);
1817 if (rc)
1818 {
1819 SetLastError(error2WinError(rc));
1820
1821 return FALSE;
1822 }
1823
1824 translateFindResults(&result,lpFindFileData);
1825 SetLastError(ERROR_SUCCESS_W);
1826 return TRUE;
1827}
1828//******************************************************************************
1829//******************************************************************************
1830BOOL OSLibDosFindNextMulti(DWORD hFindFile,WIN32_FIND_DATAA *lpFindFileData,DWORD *count)
1831{
1832 FILEFINDBUF3 *result,*data;
1833 ULONG searchCount = *count;
1834
1835 result = (FILEFINDBUF3*)malloc(searchCount*sizeof(FILEFINDBUF3));
1836 APIRET rc = DosFindNext((HDIR)hFindFile,result,searchCount*sizeof(FILEFINDBUF3),&searchCount);
1837 if (rc)
1838 {
1839 free(result);
1840 *count = 0;
1841 SetLastError(error2WinError(rc));
1842
1843 return FALSE;
1844 }
1845
1846 data = result;
1847 for (int x = 0;x < searchCount;x++)
1848 {
1849 translateFindResults(data,&lpFindFileData[x]);
1850 data = (FILEFINDBUF3*)(((DWORD)data)+data->oNextEntryOffset);
1851 }
1852 free(result);
1853 *count = searchCount;
1854
1855 SetLastError(ERROR_SUCCESS_W);
1856 return TRUE;
1857}
1858//******************************************************************************
1859//******************************************************************************
1860BOOL OSLibDosFindClose(DWORD hFindFile)
1861{
1862 APIRET rc = DosFindClose((HDIR)hFindFile);
1863 if (rc)
1864 {
1865 SetLastError(error2WinError(rc));
1866 return FALSE;
1867 }
1868
1869 SetLastError(ERROR_SUCCESS_W);
1870 return TRUE;
1871}
1872//******************************************************************************
1873#define FSATTACH_SIZE 256
1874//******************************************************************************
1875DWORD OSLibDosQueryVolumeFS(int drive, LPSTR lpFileSystemNameBuffer, DWORD nFileSystemNameSize)
1876{
1877 PFSQBUFFER2 fsinfo = (PFSQBUFFER2) alloca(FSATTACH_SIZE);
1878 ULONG cb = FSATTACH_SIZE;
1879 char drv[3] = "A:";
1880 char *fsname;
1881 APIRET rc;
1882
1883 if(lpFileSystemNameBuffer == NULL) {
1884 DebugInt3();
1885 return ERROR_INVALID_PARAMETER_W;
1886 }
1887 drv[0] = (char)('A' + drive - 1);
1888
1889 DosError(FERR_DISABLEHARDERR);
1890 rc = DosQueryFSAttach(drv, 1, FSAIL_QUERYNAME, fsinfo, &cb);
1891 DosError(FERR_ENABLEHARDERR);
1892
1893 switch(rc) {
1894 case ERROR_INVALID_DRIVE:
1895 return ERROR_INVALID_DRIVE_W;
1896 case ERROR_NO_VOLUME_LABEL:
1897 return ERROR_NO_VOLUME_LABEL_W;
1898 case NO_ERROR:
1899 break;
1900 default:
1901 return ERROR_NOT_ENOUGH_MEMORY; //whatever
1902 }
1903
1904 fsname = (char *)&fsinfo->szName[0] + fsinfo->cbName + 1;
1905
1906 /* @@@PH 2000/08/10 CMD.EXE querys with nFileSystemNameSize == 0
1907 * however does NOT expect to receive an error.
1908 */
1909 strncpy(lpFileSystemNameBuffer,
1910 fsname,
1911 nFileSystemNameSize);
1912 /*
1913 if(strlen(fsname) < nFileSystemNameSize) {
1914 strcpy(lpFileSystemNameBuffer, fsname);
1915 }
1916 else return ERROR_BUFFER_OVERFLOW_W;
1917 */
1918 return 0;
1919}
1920//******************************************************************************
1921typedef struct _FSINFOBUF
1922{
1923 ULONG ulVolser; /* Volume serial number */
1924 VOLUMELABEL vol; /* Volume lable */
1925} FSINFOBUF;
1926//******************************************************************************
1927DWORD OSLibDosQueryVolumeSerialAndName(int drive, LPDWORD lpVolumeSerialNumber,
1928 LPSTR lpVolumeNameBuffer, DWORD nVolumeNameSize)
1929{
1930 FSINFOBUF fsi;
1931 APIRET rc;
1932
1933 DosError(FERR_DISABLEHARDERR);
1934 rc = DosQueryFSInfo(drive, FSIL_VOLSER, &fsi, sizeof(fsi));
1935 DosError(FERR_ENABLEHARDERR);
1936
1937 switch(rc) {
1938 case ERROR_INVALID_DRIVE:
1939 return ERROR_INVALID_DRIVE_W;
1940 case ERROR_NO_VOLUME_LABEL:
1941 return ERROR_NO_VOLUME_LABEL_W;
1942 case NO_ERROR:
1943 break;
1944 default:
1945 return ERROR_NOT_ENOUGH_MEMORY; //whatever
1946 }
1947
1948 if(lpVolumeSerialNumber) {
1949 *lpVolumeSerialNumber = fsi.ulVolser;
1950 }
1951 if(lpVolumeNameBuffer)
1952 {
1953 if(nVolumeNameSize > fsi.vol.cch) {
1954 strcpy(lpVolumeNameBuffer, (PCHAR)fsi.vol.szVolLabel);
1955 }
1956 else return ERROR_BUFFER_OVERFLOW_W;
1957 }
1958
1959 return ERROR_SUCCESS_W;
1960}
1961//******************************************************************************
1962//******************************************************************************
1963BOOL OSLibGetDiskFreeSpace(LPSTR lpRootPathName, LPDWORD lpSectorsPerCluster,
1964 LPDWORD lpBytesPerSector, LPDWORD lpNumberOfFreeClusters,
1965 LPDWORD lpTotalNumberOfClusters)
1966{
1967 ULONG diskNum;
1968 FSALLOCATE fsAlloc;
1969 APIRET rc;
1970
1971 if(lpRootPathName == 0)
1972 diskNum = 0;
1973 else
1974 if('A' <= *lpRootPathName && *lpRootPathName <= 'Z' )
1975 diskNum = *lpRootPathName - 'A' + 1;
1976 else
1977 if('a' <= *lpRootPathName && *lpRootPathName <= 'z' )
1978 diskNum = *lpRootPathName - 'a' + 1;
1979 else
1980 diskNum = 0;
1981
1982 DosError(FERR_DISABLEHARDERR);
1983 rc = DosQueryFSInfo(diskNum, FSIL_ALLOC, &fsAlloc, sizeof(fsAlloc));
1984 DosError(FERR_ENABLEHARDERR);
1985
1986 if(rc == 0)
1987 {
1988 *lpSectorsPerCluster = fsAlloc.cSectorUnit;
1989 *lpBytesPerSector = fsAlloc.cbSector;
1990 *lpNumberOfFreeClusters = fsAlloc.cUnitAvail;
1991 *lpTotalNumberOfClusters = fsAlloc.cUnit;
1992 SetLastError(ERROR_SUCCESS_W);
1993 return TRUE;
1994 }
1995 SetLastError(error2WinError(rc));
1996 return FALSE;
1997}
1998//******************************************************************************
1999//******************************************************************************
2000BOOL OSLibDosCreatePipe(PHANDLE phfRead,
2001 PHANDLE phfWrite,
2002 LPSECURITY_ATTRIBUTES lpsa,
2003 DWORD dwSize)
2004{
2005 APIRET rc;
2006
2007 dprintf(("DosCreatePipe(%08xh,%08xh,%08xh)\n",
2008 phfRead,
2009 phfWrite,
2010 dwSize));
2011
2012 // select default buffer size
2013 if (dwSize == 0)
2014 dwSize = 4096;
2015
2016 rc = DosCreatePipe(phfRead,
2017 phfWrite,
2018 dwSize);
2019 dprintf(("DosCreatePipe rc=%d",rc));
2020 if (rc)
2021 {
2022 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER_W));
2023 return -1; // INVALID_HANDLE_VALUE
2024 }
2025 SetLastError(ERROR_SUCCESS_W);
2026 return NO_ERROR;
2027}
2028//******************************************************************************
2029//******************************************************************************
2030DWORD OSLibDosDevIOCtl( DWORD hFile, DWORD dwCat, DWORD dwFunc,
2031 PVOID pParm, DWORD dwParmMaxLen, DWORD *pdwParmLen,
2032 PVOID pData, DWORD dwDataMaxLen, DWORD *pdwDataLen)
2033{
2034 APIRET rc;
2035
2036 rc = DosDevIOCtl( (HFILE)hFile, dwCat, dwFunc,
2037 pParm, dwParmMaxLen, pdwParmLen,
2038 pData, dwDataMaxLen, pdwDataLen);
2039
2040 SetLastError(error2WinError(rc,ERROR_INVALID_HANDLE));
2041 return (DWORD)rc;
2042}
2043
2044/**
2045 * Pure wrapper for DosQueryModulName which returns the OS/2 returncode.
2046 * @returns Returncode from DosQueryModuleName.
2047 * @param hModule Handle of the module which name we query.
2048 * @param cchName Length of the output name buffer.
2049 * @param pszname Pointer to the output name buffer.
2050 * @status Completely implemented.
2051 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
2052 */
2053ULONG OSLibDosQueryModuleName(ULONG hModule, int cchName, char *pszName)
2054{
2055 return DosQueryModuleName(hModule, cchName, pszName);
2056}
2057
2058
2059HINSTANCE OSLibDosLoadModule(LPSTR szModName)
2060{
2061 APIRET rc;
2062 HMODULE hModule = NULLHANDLE;
2063 char name[ CCHMAXPATH ];
2064
2065 rc = DosLoadModule(name, CCHMAXPATH, szModName, &hModule);
2066 if(rc) {
2067 SetLastError(error2WinError(rc,ERROR_FILE_NOT_FOUND));
2068 return 0;
2069 }
2070 SetLastError(ERROR_SUCCESS_W);
2071 return hModule;
2072}
2073
2074ULONG OSLibDosQuerySysInfo(ULONG iStart, ULONG iLast, PVOID pBuf, ULONG cbBuf)
2075{
2076 APIRET rc;
2077
2078 rc = DosQuerySysInfo(iStart, iLast, pBuf, cbBuf);
2079 SetLastError(error2WinError(rc,ERROR_INVALID_HANDLE));
2080 return rc;
2081}
2082//******************************************************************************
2083//returned length is number of characters required or used for current dir
2084//*excluding* terminator
2085//******************************************************************************
2086ULONG OSLibDosQueryDir(DWORD length, LPSTR lpszCurDir)
2087{
2088 ULONG drivemap, currentdisk, len;
2089 char *lpszCurDriveAndDir = lpszCurDir +3;
2090 APIRET rc;
2091
2092 len = (length > 3) ? length - 3 : 0;
2093
2094 rc = DosQueryCurrentDir(0, lpszCurDriveAndDir, &len);
2095 if(rc != ERROR_BUFFER_OVERFLOW)
2096 {
2097 if(rc)
2098 {
2099 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER));
2100 return 0;
2101 }
2102 len = strlen(lpszCurDriveAndDir) + 3;
2103
2104 // Dir returned by DosQueryCurDir doesn't include drive, so add it
2105 DosQueryCurrentDisk(&currentdisk, &drivemap);
2106
2107 if(isupper(lpszCurDir[3])) {
2108 lpszCurDir[0] = (char)('A' - 1 + currentdisk);
2109 }
2110 else lpszCurDir[0] = (char)('a' - 1 + currentdisk);
2111
2112 lpszCurDir[1] = ':';
2113 lpszCurDir[2] = '\\';
2114 }
2115 else len += 3; // + 3 since DosQueryCurDir doesn't include drive
2116
2117 SetLastError(ERROR_SUCCESS_W);
2118 return len;
2119}
2120//******************************************************************************
2121//******************************************************************************
Note: See TracBrowser for help on using the repository browser.