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

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

added mailslot implemenation, named pipe fixes + FreeLibraryAndExitThread

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