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

Last change on this file since 5196 was 5195, checked in by bird, 25 years ago

Urg! Sent wrong parameter in to DosAllocMemEx.

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