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

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

GetSystemPowerStatus fix

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