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

Last change on this file since 5890 was 5890, checked in by achimha, 24 years ago

set last error to 2 when CreateFileA fails when creating a file

File size: 77.6 KB
Line 
1/* $Id: oslibdos.cpp,v 1.62 2001-06-02 18:48:27 achimha 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 // @@@AH 2001-06-02 Win2k SP2 returns error 2 in this case
948 int winError = error2WinError(rc);
949 if (winError == ERROR_OPEN_FAILED_W)
950 winError = ERROR_FILE_NOT_FOUND_W;
951 SetLastError(winError);
952 return INVALID_HANDLE_VALUE_W;
953 }
954 SetLastError(ERROR_SUCCESS_W);
955 return hFile;
956}
957//******************************************************************************
958//******************************************************************************
959DWORD OSLibDosOpenFile(CHAR *lpszFile, UINT fuMode)
960{
961 ULONG actionTaken = 0;
962 ULONG fileSize = 0;
963 ULONG fileAttr = FILE_NORMAL;
964 ULONG openFlag = 0;
965 ULONG openMode = 0;
966 APIRET rc = ERROR_NOT_ENOUGH_MEMORY;
967 HFILE hFile;
968
969 if(!(fuMode & (OF_CREATE_W | OF_READWRITE_W | OF_WRITE_W)))
970 {
971 openMode |= OPEN_ACCESS_READONLY;
972 openFlag |= OPEN_ACTION_OPEN_IF_EXISTS;
973 }
974 else
975 {
976 if(fuMode & OF_CREATE_W) {
977 openFlag |= OPEN_ACTION_CREATE_IF_NEW |
978 OPEN_ACTION_REPLACE_IF_EXISTS;
979 }
980 else openFlag |= OPEN_ACTION_OPEN_IF_EXISTS;
981
982 if(fuMode & OF_READWRITE_W)
983 openMode |= OPEN_ACCESS_READWRITE;
984 else
985 if(fuMode & OF_WRITE_W)
986 openMode |= OPEN_ACCESS_WRITEONLY;
987 else
988 if(fuMode & OF_CREATE_W)
989 openMode |= OPEN_ACCESS_READWRITE;
990 }
991
992 if((fuMode & OF_SHARE_DENY_WRITE_W) ||
993 !(fuMode & (OF_SHARE_DENY_READ_W | OF_SHARE_DENY_NONE_W | OF_SHARE_EXCLUSIVE_W)))
994 openMode |= OPEN_SHARE_DENYWRITE;
995 else
996 if (fuMode & OF_SHARE_DENY_NONE_W)
997 openMode |= OPEN_SHARE_DENYNONE;
998 else
999 if (fuMode & OF_SHARE_DENY_READ_W)
1000 openMode |= OPEN_SHARE_DENYREAD;
1001 else
1002 if (fuMode & OF_SHARE_EXCLUSIVE_W)
1003 openMode |= OPEN_SHARE_DENYREADWRITE;
1004
1005 rc = DosOpen((PSZ)lpszFile,
1006 &hFile,
1007 &actionTaken,
1008 fileSize,
1009 fileAttr,
1010 openFlag,
1011 openMode,
1012 NULL);
1013
1014 if(rc != NO_ERROR)
1015 {
1016 if(fuMode & OF_EXIST_W)
1017 {
1018 if(rc == ERROR_OPEN_FAILED || rc == ERROR_FILE_NOT_FOUND)
1019 {
1020 SetLastError(ERROR_FILE_NOT_FOUND_W);
1021 return HFILE_ERROR_W;
1022 }
1023 }
1024 if((rc == ERROR_OPEN_FAILED) && (openFlag & OPEN_ACTION_OPEN_IF_EXISTS))
1025 {
1026 SetLastError(ERROR_FILE_NOT_FOUND_W);
1027 }
1028 else SetLastError(error2WinError(rc));
1029
1030 return HFILE_ERROR_W;
1031 }
1032 SetLastError(ERROR_SUCCESS_W);
1033 return hFile;
1034}
1035//******************************************************************************
1036//******************************************************************************
1037BOOL OSLibDosLockFile(DWORD hFile, DWORD dwFlags,
1038 DWORD OffsetLow, DWORD OffsetHigh,
1039 DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh,
1040 LPOVERLAPPED lpOverlapped)
1041{
1042 APIRET rc;
1043
1044 // Set 5 secs timeout for locking file and no other can access this
1045 // file region
1046
1047 if(lpOverlapped) {//TODO:
1048 dprintf(("OSLibDosLockFile: overlapped lock not yet implemented!!"));
1049 }
1050 //TODO: Locking region crossing end of file is permitted. Works in OS/2??
1051 if(f64BitIO)
1052 {
1053 FILELOCKL lockRangeL;
1054
1055 lockRangeL.lOffset.ulLo = OffsetLow;
1056 lockRangeL.lOffset.ulHi = OffsetHigh;
1057 lockRangeL.lRange.ulLo = nNumberOfBytesToLockLow;
1058 lockRangeL.lRange.ulHi = nNumberOfBytesToLockHigh;
1059
1060 rc = OdinDosSetFileLocksL(hFile, NULL, &lockRangeL,
1061 (dwFlags & LOCKFILE_FAIL_IMMEDIATELY_W) ? 0 : 5000, 0);
1062 //SvL: 64 bits values are only supported by JFS
1063 // Try the 32 bits DosSetFileLocks if it fails
1064 // (TODO: should check the partition type instead)
1065 if(rc == ERROR_INVALID_PARAMETER && (OffsetHigh || nNumberOfBytesToLockHigh)) {
1066 goto oldlock;
1067 }
1068 }
1069 else
1070 {
1071oldlock:
1072 FILELOCK lockRange = { OffsetLow, nNumberOfBytesToLockLow };
1073
1074 rc = DosSetFileLocks(hFile, NULL, &lockRange,
1075 (dwFlags & LOCKFILE_FAIL_IMMEDIATELY_W) ? 0 : 5000, 0);
1076 }
1077 if(rc) {
1078 SetLastError(error2WinError(rc));
1079 return FALSE;
1080 }
1081 SetLastError(ERROR_SUCCESS_W);
1082 return TRUE;
1083}
1084//******************************************************************************
1085//******************************************************************************
1086BOOL OSLibDosUnlockFile(DWORD hFile, DWORD OffsetLow, DWORD OffsetHigh,
1087 DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh,
1088 LPOVERLAPPED lpOverlapped)
1089{
1090 APIRET rc;
1091
1092 // Set 5 secs timeout for unlocking file and no other can access this
1093 // file region
1094
1095 if(lpOverlapped) {//TODO:
1096 dprintf(("OSLibDosUnlockFile: overlapped unlock not yet implemented!!"));
1097 }
1098 if(f64BitIO)
1099 {
1100 FILELOCKL unlockRangeL;
1101
1102 unlockRangeL.lOffset.ulLo = OffsetLow;
1103 unlockRangeL.lOffset.ulHi = OffsetHigh;
1104 unlockRangeL.lRange.ulLo = nNumberOfBytesToLockLow;
1105 unlockRangeL.lRange.ulHi = nNumberOfBytesToLockHigh;
1106
1107 rc = OdinDosSetFileLocksL(hFile, &unlockRangeL, NULL, 5000, 0);
1108 //SvL: 64 bits values are only supported by JFS
1109 // Try the 32 bits DosSetFileLocks if it fails
1110 // (TODO: should check the partition type instead)
1111 if(rc == ERROR_INVALID_PARAMETER && (OffsetHigh || nNumberOfBytesToLockHigh)) {
1112 goto oldlock;
1113 }
1114 }
1115 else
1116 {
1117oldlock:
1118 FILELOCK unlockRange = { OffsetLow, nNumberOfBytesToLockLow };
1119
1120 rc = DosSetFileLocks(hFile, &unlockRange, NULL, 5000, 0);
1121 }
1122 if(rc) {
1123 SetLastError(error2WinError(rc));
1124 return FALSE;
1125 }
1126 SetLastError(ERROR_SUCCESS_W);
1127 return TRUE;
1128}
1129//******************************************************************************
1130//******************************************************************************
1131BOOL OSLibDosFlushFileBuffers(DWORD hFile)
1132{
1133 APIRET rc;
1134
1135 rc = DosResetBuffer(hFile);
1136 SetLastError(error2WinError(rc));
1137 return (rc == NO_ERROR);
1138}
1139//******************************************************************************
1140//******************************************************************************
1141DWORD OSLibDosGetFileSize(DWORD hFile, LPDWORD lpdwFileSizeHigh)
1142{
1143 APIRET rc;
1144 ULONG sizeLow;
1145
1146 if(f64BitIO)
1147 {
1148 FILESTATUS3L fsts3ConfigInfoL = {{0}};
1149 ULONG ulBufSize = sizeof(FILESTATUS3L);
1150
1151 rc = DosQueryFileInfo(hFile, FIL_STANDARDL, &fsts3ConfigInfoL, ulBufSize);
1152 if(lpdwFileSizeHigh) {
1153 *lpdwFileSizeHigh = fsts3ConfigInfoL.cbFile.ulHi;
1154 }
1155 sizeLow = fsts3ConfigInfoL.cbFile.ulLo;
1156 }
1157 else
1158 {
1159 FILESTATUS3 fsts3ConfigInfo = {{0}};
1160 ULONG ulBufSize = sizeof(FILESTATUS3);
1161
1162 if(lpdwFileSizeHigh) {
1163 *lpdwFileSizeHigh = 0;
1164 }
1165 rc = DosQueryFileInfo(hFile, FIL_STANDARD, &fsts3ConfigInfo, ulBufSize);
1166 sizeLow = fsts3ConfigInfo.cbFile;
1167 }
1168 if(rc) {
1169 SetLastError(error2WinError(rc));
1170 return -1;
1171 }
1172 SetLastError(ERROR_SUCCESS_W);
1173 return sizeLow;
1174}
1175//******************************************************************************
1176//******************************************************************************
1177DWORD OSLibDosSetFilePointer(DWORD hFile, DWORD OffsetLow, DWORD *OffsetHigh, DWORD method)
1178{
1179 LONGLONG offsetL;
1180 LONGLONG newoffsetL;
1181 APIRET rc;
1182 DWORD newoffset;
1183
1184 switch(method)
1185 {
1186 case FILE_BEGIN_W:
1187 method = FILE_BEGIN;
1188 break;
1189
1190 case FILE_CURRENT_W:
1191 method = FILE_CURRENT;
1192 break;
1193
1194 case FILE_END_W:
1195 method = FILE_END;
1196 break;
1197 }
1198
1199 // PH Note: for a negative 32-bit seek, the OS/2 64-bit version
1200 // needs to be skipped.
1201 if( (f64BitIO) && (OffsetHigh) )
1202 {
1203 offsetL.ulLo = OffsetLow;
1204 offsetL.ulHi = (OffsetHigh) ? *OffsetHigh : 0;
1205 rc = OdinDosSetFilePtrL(hFile, offsetL, method, &newoffsetL);
1206 if(OffsetHigh) {
1207 *OffsetHigh = newoffsetL.ulHi;
1208 }
1209 newoffset = newoffsetL.ulLo;
1210 }
1211 else rc = DosSetFilePtr(hFile, OffsetLow, method, &newoffset);
1212
1213 if(rc)
1214 {
1215 SetLastError(error2WinError(rc));
1216 return -1;
1217 }
1218 SetLastError(ERROR_SUCCESS_W);
1219 return newoffset;
1220}
1221//******************************************************************************
1222//******************************************************************************
1223BOOL OSLibDosSetEndOfFile(DWORD hFile)
1224{
1225 ULONG newFilePos;
1226 LONGLONG FilePosL = {0,0};
1227 LONGLONG newFilePosL;
1228 APIRET rc;
1229
1230 if(f64BitIO) {
1231 rc = OdinDosSetFilePtrL(hFile, FilePosL, FILE_CURRENT, &newFilePosL);
1232 if(rc == 0) {
1233 rc = OdinDosSetFileSizeL(hFile, newFilePosL);
1234 }
1235 }
1236 else {
1237 rc = DosSetFilePtr(hFile, 0, FILE_CURRENT, &newFilePos);
1238 if(rc == 0) {
1239 rc = DosSetFileSize(hFile, newFilePos);
1240 }
1241 }
1242 if(rc) {
1243 SetLastError(error2WinError(rc));
1244 return FALSE;
1245 }
1246 SetLastError(ERROR_SUCCESS_W);
1247 return TRUE;
1248}
1249//******************************************************************************
1250//******************************************************************************
1251BOOL OSLibDosGetFileInformationByHandle(DWORD hFile, BY_HANDLE_FILE_INFORMATION* pInfo)
1252{
1253 APIRET rc;
1254
1255 if(f64BitIO)
1256 {
1257 FILESTATUS4L statusL = { 0 };
1258
1259 rc = DosQueryFileInfo(hFile, FIL_QUERYEASIZEL,
1260 &statusL, sizeof(statusL));
1261 if(rc == NO_ERROR)
1262 {
1263 pInfo->dwFileAttributes = 0;
1264 if(!(statusL.attrFile & NOT_NORMAL))
1265 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_NORMAL_W;
1266 if(statusL.attrFile & FILE_READONLY)
1267 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_READONLY_W;
1268 if(statusL.attrFile & FILE_HIDDEN)
1269 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN_W;
1270 if(statusL.attrFile & FILE_SYSTEM)
1271 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_SYSTEM_W;
1272 if(statusL.attrFile & FILE_DIRECTORY)
1273 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY_W;
1274 if(statusL.attrFile & FILE_ARCHIVED)
1275 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_ARCHIVE_W;
1276
1277 pmDateTimeToFileTime(&statusL.fdateCreation,
1278 &statusL.ftimeCreation,
1279 &pInfo->ftCreationTime);
1280 pmDateTimeToFileTime(&statusL.fdateLastAccess,
1281 &statusL.ftimeLastAccess,
1282 &pInfo->ftLastAccessTime);
1283 pmDateTimeToFileTime(&statusL.fdateLastWrite,
1284 &statusL.ftimeLastWrite,
1285 &pInfo->ftLastWriteTime);
1286
1287 pInfo->nFileSizeHigh = statusL.cbFile.ulHi;
1288 pInfo->nFileSizeLow = statusL.cbFile.ulLo;
1289 pInfo->dwVolumeSerialNumber = 0; //todo
1290 pInfo->nNumberOfLinks = 1;
1291 pInfo->nFileIndexHigh = 0;
1292 pInfo->nFileIndexLow = 0;
1293 }
1294 }
1295 else
1296 {
1297 FILESTATUS4 status = { 0 };
1298
1299 rc = DosQueryFileInfo(hFile, FIL_QUERYEASIZE, &status,
1300 sizeof(status));
1301 if(rc == NO_ERROR)
1302 {
1303 pInfo->dwFileAttributes = 0;
1304 if(!(status.attrFile & NOT_NORMAL))
1305 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_NORMAL_W;
1306 if(status.attrFile & FILE_READONLY)
1307 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_READONLY_W;
1308 if(status.attrFile & FILE_HIDDEN)
1309 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN_W;
1310 if(status.attrFile & FILE_SYSTEM)
1311 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_SYSTEM_W;
1312 if(status.attrFile & FILE_DIRECTORY)
1313 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY_W;
1314 if(status.attrFile & FILE_ARCHIVED)
1315 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_ARCHIVE_W;
1316
1317 pmDateTimeToFileTime(&status.fdateCreation,
1318 &status.ftimeCreation,
1319 &pInfo->ftCreationTime);
1320 pmDateTimeToFileTime(&status.fdateLastAccess,
1321 &status.ftimeLastAccess,
1322 &pInfo->ftLastAccessTime);
1323 pmDateTimeToFileTime(&status.fdateLastWrite,
1324 &status.ftimeLastWrite,
1325 &pInfo->ftLastWriteTime);
1326
1327 pInfo->nFileSizeHigh = 0;
1328 pInfo->nFileSizeLow = status.cbFile;
1329 pInfo->dwVolumeSerialNumber = 0; //todo
1330 pInfo->nNumberOfLinks = 1;
1331 pInfo->nFileIndexHigh = 0;
1332 pInfo->nFileIndexLow = 0;
1333 }
1334 }
1335 if(rc) {
1336 SetLastError(error2WinError(rc));
1337 return FALSE;
1338 }
1339 SetLastError(ERROR_SUCCESS_W);
1340 return TRUE;
1341}
1342//******************************************************************************
1343//******************************************************************************
1344BOOL OSLibDosSetFileTime(DWORD hFile, WORD creationdate, WORD creationtime,
1345 WORD lastaccessdate, WORD lastaccesstime,
1346 WORD lastwritedate, WORD lastwritetime)
1347{
1348 FILESTATUS3 fileInfo;
1349 APIRET rc;
1350
1351 rc = DosQueryFileInfo(hFile, FIL_STANDARD, &fileInfo, sizeof(fileInfo));
1352
1353 if(rc == NO_ERROR)
1354 {
1355 if(creationdate && creationtime) {
1356 fileInfo.fdateCreation = *(FDATE *)&creationdate;
1357 fileInfo.ftimeCreation = *(FTIME *)&creationtime;
1358 }
1359 if(lastaccessdate && lastaccesstime) {
1360 fileInfo.fdateLastAccess = *(FDATE *)&lastaccessdate;
1361 fileInfo.ftimeLastAccess = *(FTIME *)&lastaccesstime;
1362 }
1363 if(lastwritedate && lastwritetime) {
1364 fileInfo.fdateLastWrite = *(FDATE *)&lastwritedate;
1365 fileInfo.ftimeLastWrite = *(FTIME *)&lastwritetime;
1366 }
1367
1368 rc = DosSetFileInfo(hFile, FIL_STANDARD, &fileInfo, sizeof(fileInfo));
1369 }
1370
1371 if(rc)
1372 {
1373 SetLastError(error2WinError(rc));
1374 return FALSE;
1375 }
1376 SetLastError(ERROR_SUCCESS_W);
1377 return TRUE;
1378}
1379//******************************************************************************
1380//******************************************************************************
1381BOOL OSLibDosGetFileTime(DWORD hFile, WORD *creationdate, WORD *creationtime,
1382 WORD *lastaccessdate, WORD *lastaccesstime,
1383 WORD *lastwritedate, WORD *lastwritetime)
1384{
1385 FILESTATUS3 fileInfo;
1386 APIRET rc;
1387
1388 rc = DosQueryFileInfo(hFile, FIL_STANDARD, &fileInfo, sizeof(fileInfo));
1389
1390 if(rc == NO_ERROR)
1391 {
1392 *creationdate = *(WORD *)&fileInfo.fdateCreation;
1393 *creationtime = *(WORD *)&fileInfo.ftimeCreation;
1394 *lastaccessdate = *(WORD *)&fileInfo.fdateLastAccess;
1395 *lastaccesstime = *(WORD *)&fileInfo.ftimeLastAccess;
1396 *lastwritedate = *(WORD *)&fileInfo.fdateLastWrite;
1397 *lastwritetime = *(WORD *)&fileInfo.ftimeLastWrite;
1398 }
1399
1400 if(rc)
1401 {
1402 SetLastError(error2WinError(rc));
1403 return FALSE;
1404 }
1405 SetLastError(ERROR_SUCCESS_W);
1406 return TRUE;
1407}
1408//******************************************************************************
1409//******************************************************************************
1410DWORD OSLibDosSetFilePtr2(DWORD hFile, DWORD offset, DWORD method)
1411{
1412 DWORD newoffset;
1413 APIRET rc;
1414
1415
1416 rc = DosSetFilePtr(hFile, offset, method, &newoffset);
1417 if(rc) {
1418 dprintf(("DosSetFilePtr Error rc:%d", rc));
1419 return -1;
1420 }
1421 else return newoffset;
1422}
1423//******************************************************************************
1424//******************************************************************************
1425DWORD OSLibDosDupHandle(DWORD hFile, DWORD *hNew)
1426{
1427 *hNew = -1;
1428 return DosDupHandle(hFile, hNew);
1429}
1430//******************************************************************************
1431//******************************************************************************
1432void OSLibDosDisableHardError(BOOL fTurnOff)
1433{
1434 DosError((fTurnOff) ? FERR_DISABLEHARDERR : FERR_ENABLEHARDERR);
1435}
1436//******************************************************************************
1437//Returns time spent in kernel & user mode in milliseconds
1438//******************************************************************************
1439BOOL OSLibDosQueryProcTimes(DWORD procid, ULONG *kerneltime, ULONG *usertime)
1440{
1441 APIRET rc;
1442 char *buf;
1443 ULONG size;
1444 ULONG nrthreads = 4;
1445
1446tryagain:
1447 size = sizeof(QTOPLEVEL)+sizeof(QGLOBAL)+sizeof(QPROCESS) + nrthreads*sizeof(QTHREAD);
1448 buf = (char *)malloc(size);
1449 rc = DosQuerySysState(0x1, RESERVED, procid, RESERVED, (PCHAR)buf, size);
1450
1451 if(rc) {
1452 free(buf);
1453 if(rc == ERROR_BUFFER_OVERFLOW) {
1454 nrthreads += 4;
1455 goto tryagain;
1456 }
1457 return FALSE;
1458 }
1459 PQTOPLEVEL top = (PQTOPLEVEL)buf;
1460
1461 *kerneltime = 0;
1462 *usertime = 0;
1463 for(int i=0;i<top->procdata->threadcnt;i++) {
1464 *kerneltime += top->procdata->threads[i].systime;
1465 *usertime += top->procdata->threads[i].usertime;
1466 }
1467 free(buf);
1468 return TRUE;
1469}
1470//******************************************************************************
1471//******************************************************************************
1472// TODO: implement SecurityAttributes parameter
1473DWORD OSLibDosCreateNamedPipe(LPCTSTR lpName,
1474 DWORD dwOpenMode,
1475 DWORD dwPipeMode,
1476 DWORD nMaxInstances,
1477 DWORD nOutBufferSize,
1478 DWORD nInBufferSize,
1479 DWORD nDefaultTimeOut,
1480 LPSECURITY_ATTRIBUTES lpSecurityAttributes)
1481{ DWORD dwOS2Mode = 0;
1482 DWORD dwOS2PipeMode = 0;
1483 LPSTR lpOS2Name;
1484 DWORD hPipe;
1485 DWORD rc, ulAction;
1486
1487 if (dwOpenMode & PIPE_ACCESS_DUPLEX_W)
1488 dwOS2Mode |= NP_ACCESS_DUPLEX;
1489 else
1490 if (dwOpenMode & PIPE_ACCESS_INBOUND_W)
1491 dwOS2Mode |= NP_ACCESS_INBOUND;
1492 else
1493 if (dwOpenMode & PIPE_ACCESS_OUTBOUND_W)
1494 dwOS2Mode |= NP_ACCESS_OUTBOUND;
1495 // TODO:
1496 // if(dwOpenMode & FILE_FLAG_OVERLAPPED)
1497 // if(dwOpenMode & WRITE_DAC)
1498 // if(dwOpenMode & WRITE_OWNER)
1499 // if(dwOpenMode & ACCESS_SYSTEM_SECURITY)
1500 if(dwOpenMode & FILE_FLAG_WRITE_THROUGH_W)
1501 dwOS2Mode |= NP_WRITEBEHIND; // FIXME: I'm not sure!
1502
1503 if (dwPipeMode & PIPE_WAIT_W)
1504 dwOS2PipeMode |= NP_WAIT;
1505 if (dwPipeMode & PIPE_NOWAIT_W)
1506 dwOS2PipeMode |= NP_NOWAIT;
1507 if (dwPipeMode & PIPE_READMODE_BYTE_W)
1508 dwOS2PipeMode |= NP_READMODE_BYTE;
1509 if (dwPipeMode & PIPE_READMODE_MESSAGE_W)
1510 dwOS2PipeMode |= NP_READMODE_MESSAGE;
1511 if (dwPipeMode & PIPE_TYPE_BYTE_W)
1512 dwOS2PipeMode |= NP_TYPE_BYTE;
1513 if (dwPipeMode & PIPE_TYPE_MESSAGE_W)
1514 dwOS2PipeMode |= NP_TYPE_MESSAGE;
1515
1516 if (nMaxInstances>0xff)
1517 {
1518 SetLastError(ERROR_INVALID_PARAMETER_W); // ERROR_INVALID_PARAMETER
1519 return -1; // INVALID_HANDLE_VALUE
1520 }
1521 dwOS2PipeMode |= nMaxInstances;
1522
1523 if (strstr(lpName,"\\\\."))
1524 {
1525 // If pipe is created on the local machine
1526 // we must delete string \\. because
1527 // in Windows named pipes scheme is a \\.\PIPE\pipename
1528 // but in OS/2 only \PIPE\pipename
1529 lpOS2Name = (LPSTR)lpName + 3;
1530 }
1531 else lpOS2Name = (LPSTR)lpName;
1532
1533 dprintf(("DosCreateNPipe(%s,%x,%x,%x,%x,%x)",lpOS2Name,dwOS2Mode,dwOS2PipeMode,nInBufferSize,nOutBufferSize,nDefaultTimeOut));
1534
1535 //if the windows app tries to open another instance of an existing pipe, then
1536 //we must use DosOpen here. So first try DosOpen, if that fails then we can
1537 //create the named pipe
1538 rc = DosOpen(lpOS2Name, &hPipe, &ulAction, 0, FILE_NORMAL, FILE_OPEN,
1539 ((dwOpenMode & PIPE_ACCESS_INBOUND_W) ? OPEN_ACCESS_READWRITE : OPEN_ACCESS_READONLY) |
1540 OPEN_SHARE_DENYNONE, NULL);
1541
1542 if(rc == NO_ERROR) {
1543 dprintf(("Opening of existing named pipe succeeded"));
1544 return hPipe;
1545 }
1546
1547 rc=DosCreateNPipe(lpOS2Name,
1548 &hPipe,
1549 dwOS2Mode,
1550 dwOS2PipeMode,
1551 nInBufferSize,
1552 nInBufferSize,
1553 nDefaultTimeOut); // Timeouts must be tested!
1554
1555 dprintf(("DosCreateNPipe rc=%d",rc));
1556 if (rc)
1557 {
1558 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER_W));
1559 return -1; // INVALID_HANDLE_VALUE
1560 }
1561 return hPipe;
1562}
1563//******************************************************************************
1564//******************************************************************************
1565BOOL OSLibSetNamedPipeState(DWORD hNamedPipe, DWORD dwPipeMode)
1566{
1567 ULONG dwOS2PipeMode = 0;
1568 APIRET rc;
1569
1570 if (dwPipeMode & PIPE_WAIT_W)
1571 dwOS2PipeMode |= NP_WAIT;
1572 if (dwPipeMode & PIPE_NOWAIT_W)
1573 dwOS2PipeMode |= NP_NOWAIT;
1574 if (dwPipeMode & PIPE_READMODE_BYTE_W)
1575 dwOS2PipeMode |= NP_READMODE_BYTE;
1576 if (dwPipeMode & PIPE_READMODE_MESSAGE_W)
1577 dwOS2PipeMode |= NP_READMODE_MESSAGE;
1578
1579 rc = DosSetNPHState(hNamedPipe, dwOS2PipeMode);
1580 if(rc) {
1581 SetLastError(error2WinError(rc, ERROR_INVALID_PARAMETER_W));
1582 return FALSE;
1583 }
1584 return TRUE;
1585}
1586//******************************************************************************
1587//******************************************************************************
1588DWORD OSLibDosOpenPipe(LPCTSTR lpName,
1589 DWORD fuAccess,
1590 DWORD fuShare,
1591 LPSECURITY_ATTRIBUTES lpSecurityAttributes,
1592 DWORD fuCreate,
1593 DWORD fuAttrFlags)
1594{
1595 LPSTR lpOS2Name;
1596 ULONG hPipe;
1597 ULONG rc, ulAction;
1598 ULONG openFlag = 0;
1599 ULONG openMode = 0;
1600
1601
1602 switch(fuCreate)
1603 {
1604 case CREATE_NEW_W:
1605 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_FAIL_IF_EXISTS;
1606 break;
1607 case CREATE_ALWAYS_W:
1608 /* kso 2000-11-26: Not sure if OPEN_ACTION_REPLACE_IF_EXISTS is correct here! It is correct according to
1609 * MSDN, but not according to "The Win32 API SuperBible". Anyway I haven't got time to check it out in
1610 * NT now.
1611 * The problem is that OPEN_ACTION_REPLACE_IF_EXISTS requires write access. It failes with
1612 * rc = ERROR_ACCESS_DENIED (5). Quick fix, use OPEN_IF_EXIST if readonly access.
1613 */
1614 if (fuAccess & GENERIC_WRITE_W)
1615 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS;
1616 else
1617 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
1618 break;
1619 case OPEN_EXISTING_W:
1620 openFlag |= OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
1621 break;
1622 case OPEN_ALWAYS_W:
1623 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
1624 break;
1625 case TRUNCATE_EXISTING_W:
1626 openFlag |= OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS;
1627 break;
1628 }
1629
1630 if(fuAttrFlags & FILE_FLAG_WRITE_THROUGH_W) openMode |= OPEN_FLAGS_WRITE_THROUGH;
1631 if(fuAttrFlags & FILE_FLAG_NO_BUFFERING_W) openMode |= OPEN_FLAGS_NO_CACHE;
1632 if(fuAttrFlags & FILE_FLAG_RANDOM_ACCESS_W) openMode |= OPEN_FLAGS_RANDOM;
1633 if(fuAttrFlags & FILE_FLAG_SEQUENTIAL_SCAN_W) openMode |= OPEN_FLAGS_SEQUENTIAL;
1634 // TODO: FILE_FLAG_BACKUP_SEMANTICS_W
1635 // FILE_FLAG_POSIX_SEMANTICS_W are not supported
1636
1637 //TODO: FILE_SHARE_DELETE
1638 if((fuShare & (FILE_SHARE_READ_W | FILE_SHARE_WRITE_W)) == 0 )
1639 openMode |= OPEN_SHARE_DENYREADWRITE;
1640 else
1641 if((fuShare & (FILE_SHARE_READ_W | FILE_SHARE_WRITE_W)) == (FILE_SHARE_READ_W | FILE_SHARE_WRITE_W))
1642 openMode |= OPEN_SHARE_DENYNONE;
1643 else
1644 if(fuShare & FILE_SHARE_READ_W)
1645 openMode |= OPEN_SHARE_DENYWRITE;
1646 else
1647 if(fuShare & FILE_SHARE_WRITE_W)
1648 openMode |= OPEN_SHARE_DENYREAD;
1649
1650 if(fuAccess == (GENERIC_READ_W | GENERIC_WRITE_W))
1651 openMode |= OPEN_ACCESS_READWRITE;
1652 else
1653 if(fuAccess & GENERIC_READ_W)
1654 openMode |= OPEN_ACCESS_READONLY;
1655 else
1656 if(fuAccess & GENERIC_WRITE_W)
1657 openMode |= OPEN_ACCESS_WRITEONLY;
1658
1659 if (strstr(lpName,"\\\\."))
1660 {
1661 // If pipe is created on the local machine
1662 // we must delete string \\. because
1663 // in Windows named pipes scheme is a \\.\PIPE\pipename
1664 // but in OS/2 only \PIPE\pipename
1665 lpOS2Name = (LPSTR)lpName + 3;
1666 }
1667 else lpOS2Name = (LPSTR)lpName;
1668
1669 rc = DosOpen(lpOS2Name, &hPipe, &ulAction, 0, 0,
1670 openFlag, openMode, NULL);
1671
1672 if(rc == NO_ERROR) {
1673 dprintf(("Opening of existing named pipe succeeded"));
1674 return hPipe;
1675 }
1676
1677 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER_W));
1678 return -1; // INVALID_HANDLE_VALUE
1679}
1680
1681//******************************************************************************
1682//******************************************************************************
1683// TODO: implement lpOverlapped parameter!
1684BOOL OSLibDosConnectNamedPipe(DWORD hNamedPipe, LPOVERLAPPED lpOverlapped)
1685{
1686 DWORD rc;
1687
1688 rc=DosConnectNPipe(hNamedPipe);
1689 dprintf(("DosConnectNPipe rc=%d",rc));
1690
1691 if (!rc) return (TRUE);
1692 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1693
1694 return (FALSE);
1695}
1696
1697//******************************************************************************
1698//******************************************************************************
1699BOOL OSLibDosCallNamedPipe( LPCTSTR lpNamedPipeName,
1700 LPVOID lpInBuffer,
1701 DWORD nInBufferSize,
1702 LPVOID lpOutBuffer,
1703 DWORD nOutBufferSize,
1704 LPDWORD lpBytesRead,
1705 DWORD nTimeOut )
1706{
1707 LPSTR lpOS2Name;
1708 DWORD rc;
1709
1710 if (strstr(lpNamedPipeName,"\\\\."))
1711 {
1712 // If pipe is created on the local machine
1713 // we must delete string \\. because
1714 // in Windows named pipes scheme is a \\.\PIPE\pipename
1715 // but in OS/2 only \PIPE\pipename
1716 lpOS2Name = (LPSTR)lpNamedPipeName + 3;
1717 }
1718 else lpOS2Name = (LPSTR)lpNamedPipeName;
1719
1720 rc=DosCallNPipe(lpOS2Name,
1721 lpInBuffer,
1722 nInBufferSize,
1723 lpOutBuffer,
1724 nOutBufferSize,
1725 lpBytesRead,
1726 nTimeOut );
1727
1728
1729 if (!rc) return (TRUE);
1730 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1731
1732 return (FALSE);
1733}
1734
1735//******************************************************************************
1736//******************************************************************************
1737BOOL OSLibDosTransactNamedPipe( DWORD hNamedPipe,
1738 LPVOID lpInBuffer,
1739 DWORD nInBufferSize,
1740 LPVOID lpOutBuffer,
1741 DWORD nOutBufferSize,
1742 LPDWORD lpBytesRead,
1743 LPOVERLAPPED lpOverlapped)
1744{
1745 DWORD rc;
1746
1747 rc=DosTransactNPipe(hNamedPipe,
1748 lpOutBuffer,
1749 nOutBufferSize,
1750 lpInBuffer,
1751 nInBufferSize,
1752 lpBytesRead);
1753
1754 dprintf(("DosTransactNPipe returned rc=%d");)
1755 if (!rc) return (TRUE);
1756 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1757
1758 return (FALSE);
1759}
1760
1761//******************************************************************************
1762//******************************************************************************
1763BOOL OSLibDosPeekNamedPipe(DWORD hPipe,
1764 LPVOID lpvBuffer,
1765 DWORD cbBuffer,
1766 LPDWORD lpcbRead,
1767 LPDWORD lpcbAvail,
1768 LPDWORD lpcbMessage)
1769{
1770 DWORD rc;
1771 AVAILDATA availData ={0};
1772 ULONG ulDummy;
1773
1774 rc=DosPeekNPipe(hPipe,lpvBuffer,cbBuffer,lpcbRead,&availData,&ulDummy);
1775
1776 dprintf(("DosPeekNPipe returned rc=%d",rc));
1777
1778 if (!rc)
1779 {
1780 *lpcbAvail = availData.cbpipe;
1781 *lpcbMessage = availData.cbmessage;
1782 return (TRUE);
1783 }
1784 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1785
1786 return (FALSE);
1787}
1788//******************************************************************************
1789//******************************************************************************
1790BOOL OSLibDosDisconnectNamedPipe(DWORD hPipe)
1791{
1792 DWORD rc;
1793
1794 rc=DosDisConnectNPipe(hPipe);
1795
1796 dprintf(("DosDisConnectNPipe returned rc=%d",rc));
1797
1798 if (!rc) return TRUE;
1799 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1800
1801 return (FALSE);
1802}
1803//******************************************************************************
1804//******************************************************************************
1805BOOL OSLibDosWaitNamedPipe(LPCSTR lpszNamedPipeName,
1806 DWORD dwTimeout)
1807{
1808 LPSTR lpOS2Name;
1809 DWORD rc;
1810
1811 if (strstr(lpszNamedPipeName,"\\\\."))
1812 {
1813 // If pipe is created on the local machine
1814 // we must delete string \\. because
1815 // in Windows named pipes scheme is a \\.\PIPE\pipename
1816 // but in OS/2 only \PIPE\pipename
1817 lpOS2Name = (LPSTR)lpszNamedPipeName + 3;
1818 }
1819 else lpOS2Name = (LPSTR)lpszNamedPipeName;
1820
1821 rc=DosWaitNPipe(lpOS2Name,dwTimeout);
1822
1823 dprintf(("DosWaitNPipe returned rc=%d",rc));
1824
1825 if (!rc) return TRUE;
1826 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1827
1828 return (FALSE);
1829}
1830//******************************************************************************
1831//******************************************************************************
1832BOOL isRoot(CHAR* name)
1833{
1834 if (name[1] == ':')
1835 {
1836 //local name (x:\)
1837 return (name[2] == 0) || !strchr(&name[3],'\\');
1838 } else if (name[0] == '\\')
1839 {
1840 //UNC name (\\resource\drive\)
1841 CHAR *drive,*dir;
1842
1843 drive = strchr(&name[2],'\\');
1844 if (!drive) return FALSE;
1845 dir = strchr(&drive[1],'\\');
1846 if (!dir) return TRUE;
1847 return !strchr(&dir[1],'\\');
1848 } else return FALSE; //unknown
1849}
1850//******************************************************************************
1851//******************************************************************************
1852inline CHAR system2DOSCharacter(CHAR ch)
1853{
1854 switch(ch)
1855 {
1856 case ' ':
1857 case '.':
1858 case '~':
1859 return '_';
1860
1861 default:
1862 return toupper(ch);
1863 }
1864}
1865
1866// TODO: not finished nor correct!!!!
1867VOID long2ShortName(CHAR* longName, CHAR* shortName)
1868{
1869 // check for uplink / root: "." and ".."
1870 if (longName[0] == '.')
1871 {
1872 // if ((strcmp(longName,".") == 0) || (strcmp(longName,"..") == 0))
1873 if (longName[1] == 0) // "."
1874 {
1875 shortName[0] = '.';
1876 shortName[1] = 0;
1877 return;
1878 }
1879
1880 if (longName[1] == '.' && longName[2] == 0) // ".."
1881 {
1882 shortName[0] = '.';
1883 shortName[1] = '.';
1884 shortName[2] = 0;
1885 return;
1886 }
1887 }
1888 else
1889 // check for empty name
1890 if(longName[0] == 0)
1891 {
1892 shortName[0] = 0;
1893 return;
1894 }
1895
1896 INT x;
1897 CHAR *source = longName;
1898
1899 // Test if longName is 8:3 compliant and simply copy
1900 // the filename.
1901 BOOL flag83 = TRUE;
1902
1903 // verify forbidden characters
1904 for (x = 0;
1905 (x < 8) &&
1906 (flag83 == TRUE);
1907 x++)
1908 {
1909 switch (*source)
1910 {
1911 case '.': // a period will cause the loop to abort!
1912 x=1000;
1913 break;
1914
1915 case '/': case '?':
1916 case '*': case ':':
1917 case '\\': case '"':
1918 case ' ':
1919 flag83 = FALSE;
1920 break;
1921 default:
1922 source++;
1923 break;
1924 }
1925 }
1926
1927 // verify we're on a period now
1928 if (flag83 == TRUE)
1929 if (*source != '.')
1930 flag83 = FALSE;
1931 else source++;
1932
1933 // verify extension
1934 if (flag83 == TRUE)
1935 for (INT y = 0;
1936 (y < 3) && (flag83 == TRUE);
1937 y++)
1938 {
1939 switch (*source)
1940 {
1941 case '/': case '?':
1942 case '*': case ':':
1943 case '\\': case '"':
1944 case ' ': case '.':
1945 flag83 = FALSE;
1946 break;
1947 }
1948 source++;
1949 }
1950
1951 // verify we're at the end of the string now
1952 if (flag83 == TRUE)
1953 if (*source != 0)
1954 flag83 = FALSE;
1955
1956 // OK, done
1957 if (flag83 == TRUE)
1958 {
1959 // we might not alter any character here, since
1960 // an app opening a specific file with an 8:3 "alias",
1961 // would surely fail.
1962 strcpy(shortName, longName);
1963
1964 return; // Done
1965 }
1966
1967
1968 // @@@PH
1969 shortName[0] = 0; // this function is disabled anyway ...
1970 return;
1971
1972 CHAR *dest = shortName;
1973 CHAR *ext = strrchr(longName,'.');
1974
1975 //CB: quick and dirty, real FILE~12.EXT is too slow
1976 //PH: We'd have to count the number of non-8:3-compliant files
1977 // within a directory. Or simpler: the number of files within
1978 // the current directory.
1979
1980 //8 character file name
1981 for (x = 0;x < 8;x++)
1982 {
1983 if ((source == ext) || (source[0] == 0)) break;
1984 dest[0] = system2DOSCharacter(source[0]);
1985 source++;
1986 dest++;
1987 }
1988
1989 if (source[0] == 0)
1990 {
1991 dest[0] = 0;
1992 return;
1993 }
1994
1995 if (source != ext)
1996 {
1997 //longName > 8 characters, insert ~1
1998 shortName[6] = '~';
1999 shortName[7] = '1';
2000 }
2001
2002 if (ext)
2003 {
2004 //add extension, 3 characters
2005 dest[0] = ext[0];
2006 dest++;
2007 ext++;
2008 for (x = 0;x < 3;x++)
2009 {
2010 if (ext[0] == 0) break;
2011 dest[0] = system2DOSCharacter(ext[0]);
2012 ext++;
2013 dest++;
2014 }
2015 }
2016 dest[0] = 0;
2017}
2018//******************************************************************************
2019//******************************************************************************
2020VOID translateFileResults(FILESTATUS3 *pResult,LPWIN32_FIND_DATAA pFind,CHAR* achName)
2021{
2022 CHAR* name;
2023
2024 pFind->dwReserved0 = pFind->dwReserved1 = 0;
2025 pFind->dwFileAttributes = pm2WinFileAttributes(pResult->attrFile);
2026
2027 pmDateTimeToFileTime(&pResult->fdateCreation,&pResult->ftimeCreation,&pFind->ftCreationTime);
2028 pmDateTimeToFileTime(&pResult->fdateLastAccess,&pResult->ftimeLastAccess,&pFind->ftLastAccessTime);
2029 pmDateTimeToFileTime(&pResult->fdateLastWrite,&pResult->ftimeLastWrite,&pFind->ftLastWriteTime);
2030
2031 pFind->nFileSizeHigh = 0; //CB: fixme
2032 pFind->nFileSizeLow = pResult->cbFile;
2033 name = strrchr(achName,'\\');
2034 if (name)
2035 {
2036 name++;
2037 strcpy(pFind->cFileName,name);
2038 }
2039 else
2040 pFind->cFileName[0] = 0;
2041
2042 long2ShortName(pFind->cFileName,pFind->cAlternateFileName);
2043}
2044
2045VOID translateFindResults(FILEFINDBUF3 *pResult,LPWIN32_FIND_DATAA pFind)
2046{
2047 pFind->dwFileAttributes = pm2WinFileAttributes(pResult->attrFile);
2048 pFind->dwReserved0 = pFind->dwReserved1 = 0;
2049
2050 pmDateTimeToFileTime(&pResult->fdateCreation,&pResult->ftimeCreation,&pFind->ftCreationTime);
2051 pmDateTimeToFileTime(&pResult->fdateLastAccess,&pResult->ftimeLastAccess,&pFind->ftLastAccessTime);
2052 pmDateTimeToFileTime(&pResult->fdateLastWrite,&pResult->ftimeLastWrite,&pFind->ftLastWriteTime);
2053
2054 pFind->nFileSizeHigh = 0; //CB: fixme
2055 pFind->nFileSizeLow = pResult->cbFile;
2056 strcpy(pFind->cFileName,pResult->achName);
2057 long2ShortName(pFind->cFileName,pFind->cAlternateFileName);
2058}
2059//******************************************************************************
2060//******************************************************************************
2061DWORD OSLibDosFindFirst(LPCSTR lpFileName,WIN32_FIND_DATAA* lpFindFileData)
2062{
2063 HDIR hDir = -1;
2064 ULONG attrs;
2065 FILEFINDBUF3 result;
2066 ULONG searchCount = 1;
2067
2068 attrs = FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY | FILE_ARCHIVED;
2069 result.achName[0] = 0;
2070
2071 DosError(FERR_DISABLEHARDERR | FERR_DISABLEEXCEPTION);
2072 APIRET rc = DosFindFirst((PSZ)lpFileName,&hDir,attrs,&result,sizeof(result),&searchCount,FIL_STANDARD);
2073 //PH: DosError(FERR_ENABLEHARDERR | FERR_ENABLEEXCEPTION);
2074
2075 //check root: skip "." and ".." (HPFS, not on FAT)
2076 //check in OSLibDosFindNext not necessary: "." and ".." are the first two entries
2077 if ((rc == 0) && isRoot((LPSTR)lpFileName))
2078 {
2079 while ((strcmp(result.achName,".") == 0) ||
2080 (strcmp(result.achName,"..") == 0))
2081 {
2082 result.achName[0] = 0;
2083 //PH: DosError(FERR_DISABLEHARDERR | FERR_DISABLEEXCEPTION);
2084 searchCount = 1;
2085 APIRET rc = DosFindNext(hDir,&result,sizeof(result),&searchCount);
2086 //PH: DosError(FERR_ENABLEHARDERR | FERR_ENABLEEXCEPTION);
2087 if (rc)
2088 {
2089 DosFindClose(hDir);
2090 SetLastError(error2WinError(rc));
2091
2092 DosError(FERR_ENABLEHARDERR | FERR_ENABLEEXCEPTION);
2093 return INVALID_HANDLE_VALUE_W;
2094 }
2095 }
2096 }
2097
2098 // enable i/o kernel exceptions again
2099 DosError(FERR_ENABLEHARDERR | FERR_ENABLEEXCEPTION);
2100
2101 if(rc)
2102 {
2103 DosFindClose(hDir);
2104 SetLastError(error2WinError(rc));
2105 return INVALID_HANDLE_VALUE_W;
2106 }
2107 translateFindResults(&result,lpFindFileData);
2108 SetLastError(ERROR_SUCCESS_W);
2109 return hDir;
2110}
2111//******************************************************************************
2112// NOTE: returns "." and ".." in root
2113//******************************************************************************
2114DWORD OSLibDosFindFirstMulti(LPCSTR lpFileName,WIN32_FIND_DATAA *lpFindFileData,DWORD *count)
2115{
2116 HDIR hDir = -1;
2117 ULONG attrs;
2118 FILEFINDBUF3 *result,*data;
2119 ULONG searchCount = *count;
2120
2121 attrs = FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY | FILE_ARCHIVED;
2122 result = (FILEFINDBUF3*)malloc(searchCount*sizeof(FILEFINDBUF3));
2123
2124 DosError(FERR_DISABLEHARDERR | FERR_DISABLEEXCEPTION);
2125 APIRET rc = DosFindFirst((PSZ)lpFileName,&hDir,attrs,result,searchCount*sizeof(FILEFINDBUF3),&searchCount,FIL_STANDARD);
2126 DosError(FERR_ENABLEHARDERR | FERR_ENABLEEXCEPTION);
2127 if (rc)
2128 {
2129 free(result);
2130 *count = 0;
2131 SetLastError(error2WinError(rc));
2132
2133 return INVALID_HANDLE_VALUE_W;
2134 }
2135
2136 data = result;
2137 for (int x = 0;x < searchCount;x++)
2138 {
2139 translateFindResults(data,&lpFindFileData[x]);
2140 data = (FILEFINDBUF3*)(((DWORD)data)+data->oNextEntryOffset);
2141 }
2142 free(result);
2143 *count = searchCount;
2144
2145 SetLastError(ERROR_SUCCESS_W);
2146 return hDir;
2147}
2148//******************************************************************************
2149//******************************************************************************
2150BOOL OSLibDosFindNext(DWORD hFindFile,WIN32_FIND_DATAA *lpFindFileData)
2151{
2152 FILEFINDBUF3 result;
2153 ULONG searchCount = 1;
2154
2155 APIRET rc = DosFindNext((HDIR)hFindFile,&result,sizeof(result),&searchCount);
2156 if (rc)
2157 {
2158 SetLastError(error2WinError(rc));
2159
2160 return FALSE;
2161 }
2162
2163 translateFindResults(&result,lpFindFileData);
2164 SetLastError(ERROR_SUCCESS_W);
2165 return TRUE;
2166}
2167//******************************************************************************
2168//******************************************************************************
2169BOOL OSLibDosFindNextMulti(DWORD hFindFile,WIN32_FIND_DATAA *lpFindFileData,DWORD *count)
2170{
2171 FILEFINDBUF3 *result,*data;
2172 ULONG searchCount = *count;
2173
2174 result = (FILEFINDBUF3*)malloc(searchCount*sizeof(FILEFINDBUF3));
2175 APIRET rc = DosFindNext((HDIR)hFindFile,result,searchCount*sizeof(FILEFINDBUF3),&searchCount);
2176 if (rc)
2177 {
2178 free(result);
2179 *count = 0;
2180 SetLastError(error2WinError(rc));
2181
2182 return FALSE;
2183 }
2184
2185 data = result;
2186 for (int x = 0;x < searchCount;x++)
2187 {
2188 translateFindResults(data,&lpFindFileData[x]);
2189 data = (FILEFINDBUF3*)(((DWORD)data)+data->oNextEntryOffset);
2190 }
2191 free(result);
2192 *count = searchCount;
2193
2194 SetLastError(ERROR_SUCCESS_W);
2195 return TRUE;
2196}
2197//******************************************************************************
2198//******************************************************************************
2199BOOL OSLibDosFindClose(DWORD hFindFile)
2200{
2201 APIRET rc = DosFindClose((HDIR)hFindFile);
2202 if (rc)
2203 {
2204 SetLastError(error2WinError(rc));
2205 return FALSE;
2206 }
2207
2208 SetLastError(ERROR_SUCCESS_W);
2209 return TRUE;
2210}
2211//******************************************************************************
2212#define FSATTACH_SIZE 256
2213//******************************************************************************
2214DWORD OSLibDosQueryVolumeFS(int drive, LPSTR lpFileSystemNameBuffer, DWORD nFileSystemNameSize)
2215{
2216 PFSQBUFFER2 fsinfo = (PFSQBUFFER2) alloca(FSATTACH_SIZE);
2217 ULONG cb = FSATTACH_SIZE;
2218 char drv[3] = "A:";
2219 char *fsname;
2220 APIRET rc;
2221
2222 if(lpFileSystemNameBuffer == NULL) {
2223 DebugInt3();
2224 return ERROR_INVALID_PARAMETER_W;
2225 }
2226 drv[0] = (char)('A' + drive - 1);
2227
2228 DosError(FERR_DISABLEHARDERR);
2229 rc = DosQueryFSAttach(drv, 1, FSAIL_QUERYNAME, fsinfo, &cb);
2230 DosError(FERR_ENABLEHARDERR);
2231
2232 switch(rc) {
2233 case ERROR_INVALID_DRIVE:
2234 return ERROR_INVALID_DRIVE_W;
2235 case ERROR_NO_VOLUME_LABEL:
2236 return ERROR_NO_VOLUME_LABEL_W;
2237 case NO_ERROR:
2238 break;
2239 default:
2240 return ERROR_NOT_ENOUGH_MEMORY; //whatever
2241 }
2242
2243 fsname = (char *)&fsinfo->szName[0] + fsinfo->cbName + 1;
2244
2245 /* @@@PH 2000/08/10 CMD.EXE querys with nFileSystemNameSize == 0
2246 * however does NOT expect to receive an error.
2247 */
2248 strncpy(lpFileSystemNameBuffer,
2249 fsname,
2250 nFileSystemNameSize);
2251 /*
2252 if(strlen(fsname) < nFileSystemNameSize) {
2253 strcpy(lpFileSystemNameBuffer, fsname);
2254 }
2255 else return ERROR_BUFFER_OVERFLOW_W;
2256 */
2257 return 0;
2258}
2259//******************************************************************************
2260typedef struct _FSINFOBUF
2261{
2262 ULONG ulVolser; /* Volume serial number */
2263 VOLUMELABEL vol; /* Volume lable */
2264} FSINFOBUF;
2265//******************************************************************************
2266DWORD OSLibDosQueryVolumeSerialAndName(int drive, LPDWORD lpVolumeSerialNumber,
2267 LPSTR lpVolumeNameBuffer, DWORD nVolumeNameSize)
2268{
2269 FSINFOBUF fsi;
2270 APIRET rc;
2271
2272 DosError(FERR_DISABLEHARDERR);
2273 rc = DosQueryFSInfo(drive, FSIL_VOLSER, &fsi, sizeof(fsi));
2274 DosError(FERR_ENABLEHARDERR);
2275
2276 switch(rc) {
2277 case ERROR_INVALID_DRIVE:
2278 return ERROR_INVALID_DRIVE_W;
2279 case ERROR_NO_VOLUME_LABEL:
2280 return ERROR_NO_VOLUME_LABEL_W;
2281 case NO_ERROR:
2282 break;
2283 default:
2284 return ERROR_NOT_ENOUGH_MEMORY; //whatever
2285 }
2286
2287 if(lpVolumeSerialNumber) {
2288 *lpVolumeSerialNumber = fsi.ulVolser;
2289 }
2290 if(lpVolumeNameBuffer)
2291 {
2292 if(nVolumeNameSize > fsi.vol.cch) {
2293 strcpy(lpVolumeNameBuffer, (PCHAR)fsi.vol.szVolLabel);
2294 }
2295 else return ERROR_BUFFER_OVERFLOW_W;
2296 }
2297
2298 return ERROR_SUCCESS_W;
2299}
2300//******************************************************************************
2301//******************************************************************************
2302BOOL OSLibGetDiskFreeSpace(LPSTR lpRootPathName, LPDWORD lpSectorsPerCluster,
2303 LPDWORD lpBytesPerSector, LPDWORD lpNumberOfFreeClusters,
2304 LPDWORD lpTotalNumberOfClusters)
2305{
2306 ULONG diskNum;
2307 FSALLOCATE fsAlloc;
2308 APIRET rc;
2309
2310 if(lpRootPathName == 0)
2311 diskNum = 0;
2312 else
2313 if('A' <= *lpRootPathName && *lpRootPathName <= 'Z' )
2314 diskNum = *lpRootPathName - 'A' + 1;
2315 else
2316 if('a' <= *lpRootPathName && *lpRootPathName <= 'z' )
2317 diskNum = *lpRootPathName - 'a' + 1;
2318 else
2319 diskNum = 0;
2320
2321 DosError(FERR_DISABLEHARDERR);
2322 rc = DosQueryFSInfo(diskNum, FSIL_ALLOC, &fsAlloc, sizeof(fsAlloc));
2323 DosError(FERR_ENABLEHARDERR);
2324
2325 if(rc == 0)
2326 {
2327 *lpSectorsPerCluster = fsAlloc.cSectorUnit;
2328 *lpBytesPerSector = fsAlloc.cbSector;
2329 *lpNumberOfFreeClusters = fsAlloc.cUnitAvail;
2330 *lpTotalNumberOfClusters = fsAlloc.cUnit;
2331 SetLastError(ERROR_SUCCESS_W);
2332 return TRUE;
2333 }
2334 SetLastError(error2WinError(rc));
2335 return FALSE;
2336}
2337//******************************************************************************
2338//Returns bit map where with the mapping of the logical drives
2339//******************************************************************************
2340ULONG OSLibGetLogicalDrives()
2341{
2342 ULONG ulDriveNum = 0; /* Drive number (A=1, B=2, C=3, ...) */
2343 ULONG ulDriveMap = 0; /* Mapping of valid drives */
2344 APIRET rc;
2345
2346 rc = DosQueryCurrentDisk(&ulDriveNum, &ulDriveMap);
2347 if(rc) {
2348 DebugInt3();
2349 SetLastError(error2WinError(rc));
2350 return 0;
2351 }
2352 return ulDriveMap;
2353}
2354//******************************************************************************
2355//******************************************************************************
2356ULONG OSLibDosQueryCurrentDisk()
2357
2358{
2359 ULONG ulDriveNum = 0; /* Drive number (A=1, B=2, C=3, ...) */
2360 ULONG ulDriveMap = 0; /* Mapping of valid drives */
2361 APIRET rc;
2362
2363 rc = DosQueryCurrentDisk(&ulDriveNum, &ulDriveMap);
2364 if(rc) {
2365 DebugInt3();
2366 SetLastError(error2WinError(rc));
2367 return 0;
2368 }
2369 return ulDriveNum;
2370}
2371//******************************************************************************
2372//******************************************************************************
2373BOOL OSLibDosCreatePipe(PHANDLE phfRead,
2374 PHANDLE phfWrite,
2375 LPSECURITY_ATTRIBUTES lpsa,
2376 DWORD dwSize)
2377{
2378 APIRET rc;
2379
2380 dprintf(("DosCreatePipe(%08xh,%08xh,%08xh)\n",
2381 phfRead,
2382 phfWrite,
2383 dwSize));
2384
2385 // select default buffer size
2386 if (dwSize == 0)
2387 dwSize = 4096;
2388
2389 rc = DosCreatePipe(phfRead,
2390 phfWrite,
2391 dwSize);
2392 dprintf(("DosCreatePipe rc=%d",rc));
2393 if (rc)
2394 {
2395 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER_W));
2396 return -1; // INVALID_HANDLE_VALUE
2397 }
2398 SetLastError(ERROR_SUCCESS_W);
2399 return NO_ERROR;
2400}
2401//******************************************************************************
2402//******************************************************************************
2403DWORD OSLibDosDevIOCtl( DWORD hFile, DWORD dwCat, DWORD dwFunc,
2404 PVOID pParm, DWORD dwParmMaxLen, DWORD *pdwParmLen,
2405 PVOID pData, DWORD dwDataMaxLen, DWORD *pdwDataLen)
2406{
2407 APIRET rc;
2408
2409 rc = DosDevIOCtl( (HFILE)hFile, dwCat, dwFunc,
2410 pParm, dwParmMaxLen, pdwParmLen,
2411 pData, dwDataMaxLen, pdwDataLen);
2412
2413 SetLastError(error2WinError(rc,ERROR_INVALID_HANDLE));
2414 return (DWORD)rc;
2415}
2416
2417/**
2418 * Pure wrapper for DosQueryModulName which returns the OS/2 returncode.
2419 * @returns Returncode from DosQueryModuleName.
2420 * @param hModule Handle of the module which name we query.
2421 * @param cchName Length of the output name buffer.
2422 * @param pszname Pointer to the output name buffer.
2423 * @status Completely implemented.
2424 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
2425 */
2426ULONG OSLibDosQueryModuleName(ULONG hModule, int cchName, char *pszName)
2427{
2428 return DosQueryModuleName(hModule, cchName, pszName);
2429}
2430
2431
2432HINSTANCE OSLibDosLoadModule(LPSTR szModName)
2433{
2434 APIRET rc;
2435 HMODULE hModule = NULLHANDLE;
2436 char name[ CCHMAXPATH ];
2437
2438 rc = DosLoadModule(name, CCHMAXPATH, szModName, &hModule);
2439 if(rc) {
2440 SetLastError(error2WinError(rc,ERROR_FILE_NOT_FOUND));
2441 return 0;
2442 }
2443 SetLastError(ERROR_SUCCESS_W);
2444 return hModule;
2445}
2446
2447ULONG OSLibDosQuerySysInfo(ULONG iStart, ULONG iLast, PVOID pBuf, ULONG cbBuf)
2448{
2449 APIRET rc;
2450
2451 rc = DosQuerySysInfo(iStart, iLast, pBuf, cbBuf);
2452 SetLastError(error2WinError(rc,ERROR_INVALID_HANDLE));
2453 return rc;
2454}
2455//******************************************************************************
2456//returned length is number of characters required or used for current dir
2457//*excluding* terminator
2458//******************************************************************************
2459ULONG OSLibDosQueryDir(DWORD length, LPSTR lpszCurDir)
2460{
2461 ULONG drivemap, currentdisk, len;
2462 char *lpszCurDriveAndDir = lpszCurDir +3;
2463 APIRET rc;
2464
2465 len = (length > 3) ? length - 3 : 0;
2466
2467 rc = DosQueryCurrentDir(0, lpszCurDriveAndDir, &len);
2468 if(rc != ERROR_BUFFER_OVERFLOW)
2469 {
2470 if(rc)
2471 {
2472 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER));
2473 return 0;
2474 }
2475 len = strlen(lpszCurDriveAndDir) + 3;
2476
2477 // Dir returned by DosQueryCurDir doesn't include drive, so add it
2478 DosQueryCurrentDisk(&currentdisk, &drivemap);
2479
2480 if(isupper(lpszCurDir[3])) {
2481 lpszCurDir[0] = (char)('A' - 1 + currentdisk);
2482 }
2483 else lpszCurDir[0] = (char)('a' - 1 + currentdisk);
2484
2485 lpszCurDir[1] = ':';
2486 lpszCurDir[2] = '\\';
2487 }
2488 else len += 3; // + 3 since DosQueryCurDir doesn't include drive
2489
2490 SetLastError(ERROR_SUCCESS_W);
2491 return len;
2492}
2493//******************************************************************************
2494//******************************************************************************
Note: See TracBrowser for help on using the repository browser.