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

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

Use DosLoadModule instead of O32_LoadLibrary; changed log strings in exception dump (.dll/.exe)

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