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

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

added ERROR_INVALID_NAME error conversion

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