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

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

Rewrote CopyFile, MoveFile & RemoveDirectory

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