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

Last change on this file since 3642 was 3642, checked in by sandervl, 25 years ago

Rewrote file io apis

File size: 57.6 KB
Line 
1/* $Id: oslibdos.cpp,v 1.29 2000-06-01 11:28:47 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 *
10 * Project Odin Software License can be found in LICENSE.TXT
11 *
12 */
13#define INCL_BASE
14#define INCL_DOSEXCEPTIONS
15#define INCL_DOSMEMMGR
16#define INCL_DOSPROCESS
17#define INCL_DOSFILEMGR
18#define INCL_DOSERRORS
19#define INCL_NPIPES
20#include <os2wrap.h> //Odin32 OS/2 api wrappers
21#include <stdlib.h>
22#include <stdio.h>
23#include <string.h>
24#include <ctype.h>
25#include <win32api.h>
26#include <winconst.h>
27#include <misc.h>
28#include "initterm.h"
29#include "oslibdos.h"
30#include "dosqss.h"
31
32#define DBG_LOCALLOG DBG_oslibdos
33#include "dbglocal.h"
34
35static PROC_DosSetFileSizeL DosSetFileSizeLProc = 0;
36static PROC_DosSetFilePtrL DosSetFilePtrLProc = 0;
37static PROC_DosSetFileLocksL DosSetFileLocksLProc = 0;
38static BOOL f64BitIO = FALSE;
39//******************************************************************************
40//******************************************************************************
41void OSLibInitWSeBFileIO()
42{
43 HMODULE hDoscalls;
44
45 if(DosQueryModuleHandle("DOSCALLS", &hDoscalls) != NO_ERROR) {
46 return;
47 }
48 if(DosQueryProcAddr(hDoscalls, 989, NULL, (PFN *)&DosSetFileSizeLProc) != NO_ERROR) {
49 return;
50 }
51 if(DosQueryProcAddr(hDoscalls, 988, NULL, (PFN *)&DosSetFilePtrLProc) != NO_ERROR) {
52 return;
53 }
54 if(DosQueryProcAddr(hDoscalls, 986, NULL, (PFN *)&DosSetFileLocksLProc) != NO_ERROR) {
55 return;
56 }
57 f64BitIO = TRUE;
58}
59//******************************************************************************
60//******************************************************************************
61APIRET OdinDosSetFileSizeL(HFILE hFile, LONGLONG cbSize)
62{
63 APIRET yyrc;
64 USHORT sel = RestoreOS2FS();
65
66 yyrc = DosSetFileSizeLProc(hFile, cbSize);
67 SetFS(sel);
68
69 return yyrc;
70}
71//******************************************************************************
72//******************************************************************************
73APIRET OdinDosSetFilePtrL(HFILE hFile, LONGLONG ib, ULONG method, PLONGLONG ibActual)
74{
75 APIRET yyrc;
76 USHORT sel = RestoreOS2FS();
77
78 yyrc = DosSetFilePtrLProc(hFile, ib, method, ibActual);
79 SetFS(sel);
80
81 return yyrc;
82}
83//******************************************************************************
84//******************************************************************************
85APIRET OdinDosSetFileLocksL(HFILE hFile, PFILELOCKL pflUnlock, PFILELOCKL pflLock,
86 ULONG timeout, ULONG flags)
87{
88 APIRET yyrc;
89 USHORT sel = RestoreOS2FS();
90
91 yyrc = DosSetFileLocksLProc(hFile, pflUnlock, pflLock, timeout, flags);
92 SetFS(sel);
93
94 return yyrc;
95}
96//******************************************************************************
97// translate OS/2 error codes to Windows codes
98// NOTE: add all codes you need, list is not complete!
99//******************************************************************************
100DWORD error2WinError(APIRET rc,DWORD defaultCode = ERROR_NOT_ENOUGH_MEMORY_W)
101{
102 switch (rc)
103 {
104 case NO_ERROR: //0
105 return ERROR_SUCCESS_W;
106
107 case ERROR_INVALID_FUNCTION: //1
108 return ERROR_INVALID_FUNCTION_W;
109
110 case ERROR_FILE_NOT_FOUND: //2
111 return ERROR_FILE_NOT_FOUND_W;
112
113 case ERROR_PATH_NOT_FOUND: //3
114 return ERROR_PATH_NOT_FOUND_W;
115
116 case ERROR_TOO_MANY_OPEN_FILES: //4
117 return ERROR_TOO_MANY_OPEN_FILES_W;
118
119 case ERROR_ACCESS_DENIED: //5
120 return ERROR_ACCESS_DENIED_W;
121
122 case ERROR_INVALID_HANDLE: //6
123 return ERROR_INVALID_HANDLE_W;
124
125 case ERROR_NOT_ENOUGH_MEMORY: //8
126 return ERROR_NOT_ENOUGH_MEMORY_W;
127
128 case ERROR_BAD_FORMAT: //11
129 return ERROR_BAD_FORMAT_W;
130
131 case ERROR_INVALID_ACCESS: //12
132 return ERROR_INVALID_ACCESS_W;
133
134 case ERROR_NO_MORE_FILES: //18
135 return ERROR_NO_MORE_FILES_W;
136
137 case ERROR_WRITE_PROTECT: //19
138 return ERROR_WRITE_PROTECT_W;
139
140 case ERROR_NOT_DOS_DISK: //26
141 return ERROR_NOT_DOS_DISK_W;
142
143 case ERROR_WRITE_FAULT: //29
144 return ERROR_WRITE_FAULT_W;
145
146 case ERROR_SHARING_VIOLATION: //32
147 return ERROR_SHARING_VIOLATION_W;
148
149 case ERROR_LOCK_VIOLATION: //32
150 return ERROR_LOCK_VIOLATION_W;
151
152 case ERROR_SHARING_BUFFER_EXCEEDED: //36
153 return ERROR_SHARING_BUFFER_EXCEEDED_W;
154
155 case ERROR_CANNOT_MAKE: //82
156 return ERROR_CANNOT_MAKE_W;
157
158 case ERROR_OUT_OF_STRUCTURES: //84
159 return ERROR_OUT_OF_STRUCTURES_W;
160
161 case ERROR_INVALID_PARAMETER: //87
162 return ERROR_INVALID_PARAMETER_W;
163
164 case ERROR_INTERRUPT: //95
165 return ERROR_INVALID_AT_INTERRUPT_TIME_W; //CB: right???
166
167 case ERROR_DEVICE_IN_USE: //99
168 return ERROR_DEVICE_IN_USE_W;
169
170 case ERROR_DRIVE_LOCKED: //108
171 return ERROR_DRIVE_LOCKED_W;
172
173 case ERROR_BROKEN_PIPE: //109
174 return ERROR_BROKEN_PIPE_W;
175
176 case ERROR_OPEN_FAILED: //110
177 return ERROR_OPEN_FAILED_W;
178
179 case ERROR_BUFFER_OVERFLOW: //111
180 return ERROR_BUFFER_OVERFLOW_W;
181
182 case ERROR_DISK_FULL: //112
183 return ERROR_DISK_FULL_W;
184
185 case ERROR_NO_MORE_SEARCH_HANDLES: //113
186 return ERROR_NO_MORE_SEARCH_HANDLES_W;
187
188 case ERROR_SEM_TIMEOUT: //121
189 return ERROR_SEM_TIMEOUT_W;
190
191 case ERROR_DIRECT_ACCESS_HANDLE: //130
192 return ERROR_DIRECT_ACCESS_HANDLE_W;
193
194 case ERROR_NEGATIVE_SEEK: //131
195 return ERROR_NEGATIVE_SEEK;
196
197 case ERROR_SEEK_ON_DEVICE: //132
198 return ERROR_SEEK_ON_DEVICE_W;
199
200 case ERROR_DISCARDED: //157
201 return ERROR_DISCARDED_W;
202
203 case ERROR_FILENAME_EXCED_RANGE: //206
204 return ERROR_FILENAME_EXCED_RANGE_W;
205
206 case ERROR_META_EXPANSION_TOO_LONG: //208
207 return ERROR_META_EXPANSION_TOO_LONG_W;
208
209 case ERROR_BAD_PIPE: //230
210 return ERROR_BAD_PIPE_W;
211
212 case ERROR_PIPE_BUSY: //231
213 return ERROR_PIPE_BUSY_W;
214
215 case ERROR_NO_DATA: //232
216 return ERROR_NO_DATA_W;
217
218 case ERROR_PIPE_NOT_CONNECTED: //233
219 return ERROR_PIPE_NOT_CONNECTED_W;
220
221 case ERROR_MORE_DATA: //234
222 return ERROR_MORE_DATA_W;
223
224 case ERROR_INVALID_EA_NAME: //254
225 return ERROR_INVALID_EA_NAME_W;
226
227 case ERROR_EA_LIST_INCONSISTENT: //255
228 return ERROR_EA_LIST_INCONSISTENT_W;
229
230 case ERROR_EAS_DIDNT_FIT: //275
231 return ERROR_EAS_DIDNT_FIT;
232
233 default:
234 dprintf(("WARNING: error2WinError: error %d not included!!!!", rc));
235 return defaultCode;
236 }
237}
238//******************************************************************************
239//TODO: Assumes entire memory range has the same protection flags!
240//TODO: Check if this works for code aliases...
241//******************************************************************************
242DWORD OSLibDosAliasMem(LPVOID pb, ULONG cb, LPVOID *ppbAlias, ULONG fl)
243{
244 DWORD rc;
245 DWORD attr;
246 DWORD size = cb;
247
248 cb = (cb-1) & ~0xfff;
249 cb+= PAGE_SIZE;
250
251 rc = DosQueryMem(pb, &size, &attr);
252 if(rc) {
253 dprintf(("OSLibDosAliasMem: DosQueryMem %x %x return %d", pb, size, rc));
254 return rc;
255 }
256 size = (size-1) & ~0xfff;
257 size+= PAGE_SIZE;
258 if(size != cb) {
259 dprintf(("ERROR: OSLibDosAliasMem: size != cb (%x!=%x)!!!!!!!!", size, cb));
260 //ignore this and continue return 5;
261 attr = fl; //just use original protection flags (NOT CORRECT)
262 }
263 attr &= (PAG_READ|PAG_WRITE|PAG_EXECUTE|PAG_GUARD|PAG_DEFAULT);
264 if(attr != fl) {
265 rc = DosSetMem(pb, size, fl);
266 if(rc) {
267 dprintf(("OSLibDosAliasMem: DosSetMem %x %x return %d", pb, size, rc));
268 attr = fl;
269 //just continue for now
270 //return rc;
271 }
272 }
273 rc = DosAliasMem(pb, cb, ppbAlias, 2);
274 if(rc) {
275 dprintf(("OSLibDosAliasMem: DosAliasMem %x %x returned %d", pb, cb, rc));
276 return rc;
277 }
278 if(attr != fl) {
279 rc = DosSetMem(pb, size, attr);
280 if(rc) {
281 dprintf(("OSLibDosAliasMem: DosSetMem (2) %x %x return %d", pb, size, rc));
282 return rc;
283 }
284 }
285 return 0;
286}
287//******************************************************************************
288//NT returns addresses aligned at 64k, so we do too.
289//******************************************************************************
290DWORD OSLibDosAllocMem(LPVOID *lplpMemAddr, DWORD size, DWORD flags)
291{
292 LPVOID memaddr;
293 DWORD offset;
294 APIRET rc;
295
296 rc = DosAllocMem(&memaddr, size, PAG_READ | flAllocMem);
297 if(rc) {
298 return rc;
299 }
300 DosEnterCritSec();
301 DosFreeMem(memaddr);
302 offset = (DWORD)memaddr & 0xFFFF;
303 if(offset) {
304 DosAllocMem(&memaddr, 64*1024 - offset, PAG_READ | flAllocMem);
305 }
306 rc = DosAllocMem(lplpMemAddr, size, flags | flAllocMem);
307 DosExitCritSec();
308 if((DWORD)*lplpMemAddr & 0xFFFF) {//still not at 64k boundary?
309 DosFreeMem(*lplpMemAddr);
310 rc = OSLibDosAllocMem(lplpMemAddr, size, flags);
311 }
312 if(offset) {
313 DosFreeMem(memaddr);
314 }
315
316 return rc;
317}
318//******************************************************************************
319//******************************************************************************
320DWORD OSLibDosFreeMem(LPVOID lpMemAddr)
321{
322 return DosFreeMem(lpMemAddr);
323}
324//******************************************************************************
325//NOTE: If name == NULL, allocated gettable unnamed shared memory
326//******************************************************************************
327DWORD OSLibDosAllocSharedMem(LPVOID *lplpMemAddr, DWORD size, DWORD flags, LPSTR name)
328{
329 APIRET rc;
330 char *sharedmemname = NULL;
331
332 if(name) {
333 sharedmemname = (char *)malloc(strlen(name) + 16);
334 strcpy(sharedmemname, "\\SHAREMEM\\");
335 strcat(sharedmemname, name);
336 }
337 else flags |= OBJ_GETTABLE;
338
339 rc = DosAllocSharedMem(lplpMemAddr, sharedmemname, size, flags);
340 if(name) {
341 free(sharedmemname);
342 }
343 return rc;
344}
345//******************************************************************************
346//NOTE: If name == NULL, assume gettable unnamed shared memory
347//******************************************************************************
348DWORD OSLibDosGetNamedSharedMem(LPVOID *lplpMemAddr, LPSTR name)
349{
350 APIRET rc;
351 char *sharedmemname = NULL;
352
353 if(name) {
354 sharedmemname = (char *)malloc(strlen(name) + 16);
355 strcpy(sharedmemname, "\\SHAREMEM\\");
356 strcat(sharedmemname, name);
357 rc = DosGetNamedSharedMem(lplpMemAddr, sharedmemname, PAG_READ|PAG_WRITE);
358 if(name) {
359 free(sharedmemname);
360 }
361 }
362 else rc = DosGetSharedMem((LPVOID)*(DWORD *)lplpMemAddr, PAG_READ|PAG_WRITE);
363
364 return rc;
365}
366//******************************************************************************
367//******************************************************************************
368DWORD OSLibDosQueryMem(LPVOID lpMemAddr, DWORD *lpRangeSize, DWORD *lpAttr)
369{
370 return DosQueryMem(lpMemAddr, lpRangeSize, lpAttr);
371}
372//******************************************************************************
373//******************************************************************************
374DWORD OSLibDosSetMem(LPVOID lpMemAddr, DWORD size, DWORD flags)
375{
376 APIRET rc;
377
378 rc = DosSetMem(lpMemAddr, size, flags);
379 switch(rc) {
380 case ERROR_INVALID_ADDRESS:
381 return OSLIB_ERROR_INVALID_ADDRESS;
382 case ERROR_ACCESS_DENIED:
383 return OSLIB_ERROR_ACCESS_DENIED;
384 default:
385 return rc;
386 }
387}
388//******************************************************************************
389//******************************************************************************
390DWORD OSLibDosOpen(char *lpszFileName, DWORD flags)
391{
392 APIRET rc;
393 HFILE hFile;
394 ULONG ulAction;
395 DWORD os2flags = OPEN_FLAGS_NOINHERIT;
396
397
398 if(flags & OSLIB_ACCESS_READONLY)
399 os2flags |= OPEN_ACCESS_READONLY;
400 else
401 if(flags & OSLIB_ACCESS_READWRITE)
402 os2flags |= OPEN_ACCESS_READWRITE;
403
404 if(flags & OSLIB_ACCESS_SHAREDENYNONE)
405 os2flags |= OPEN_SHARE_DENYNONE;
406 else
407 if(flags & OSLIB_ACCESS_SHAREDENYREAD)
408 os2flags |= OPEN_SHARE_DENYREAD;
409 else
410 if(flags & OSLIB_ACCESS_SHAREDENYWRITE)
411 os2flags |= OPEN_SHARE_DENYWRITE;
412
413tryopen:
414 rc = DosOpen(lpszFileName, /* File path name */
415 &hFile, /* File handle */
416 &ulAction, /* Action taken */
417 0L, /* File primary allocation */
418 0L, /* File attribute */
419 OPEN_ACTION_FAIL_IF_NEW |
420 OPEN_ACTION_OPEN_IF_EXISTS, /* Open function type */
421 os2flags,
422 0L); /* No extended attribute */
423
424 if(rc) {
425 if(rc == ERROR_TOO_MANY_OPEN_FILES) {
426 ULONG CurMaxFH;
427 LONG ReqCount = 32;
428
429 rc = DosSetRelMaxFH(&ReqCount, &CurMaxFH);
430 if(rc) {
431 dprintf(("DosSetRelMaxFH returned %d", rc));
432 return 0;
433 }
434 dprintf(("DosOpen failed -> increased nr open files to %d", CurMaxFH));
435 goto tryopen;
436 }
437 return 0;
438 }
439 else return hFile;
440}
441//******************************************************************************
442//******************************************************************************
443DWORD OSLibDosClose(DWORD hFile)
444{
445 return DosClose(hFile);
446}
447//******************************************************************************
448//******************************************************************************
449DWORD OSLibDosChangeMaxFileHandles()
450{
451 ULONG CurMaxFH;
452 LONG ReqCount = 0;
453 APIRET rc;
454
455 rc = DosSetRelMaxFH(&ReqCount, &CurMaxFH);
456 if(rc) {
457 dprintf(("DosSetRelMaxFH returned %d", rc));
458 return rc;
459 }
460 if(ReqCount + ODIN_INCREMENT_MAX_FILEHANDLES > CurMaxFH) {
461 ReqCount = CurMaxFH + ODIN_INCREMENT_MAX_FILEHANDLES;
462 rc = DosSetRelMaxFH(&ReqCount, &CurMaxFH);
463 if(rc) {
464 dprintf(("DosSetRelMaxFH returned %d", rc));
465 return rc;
466 }
467 }
468 return 0;
469}
470//******************************************************************************
471//******************************************************************************
472DWORD OSLibDosSetInitialMaxFileHandles(DWORD maxhandles)
473{
474 ULONG CurMaxFH;
475 LONG ReqCount = 0;
476 APIRET rc;
477
478 rc = DosSetRelMaxFH(&ReqCount, &CurMaxFH);
479 if(rc) {
480 dprintf(("DosSetRelMaxFH returned %d", rc));
481 return rc;
482 }
483 if(CurMaxFH < maxhandles) {
484 rc = DosSetMaxFH(maxhandles);
485 if(rc) {
486 dprintf(("DosSetMaxFH returned %d", rc));
487 return rc;
488 }
489 }
490 return 0;
491}
492//******************************************************************************
493//******************************************************************************
494BOOL OSLibDosRead(DWORD hFile, LPVOID lpBuffer, DWORD size, DWORD *nrBytesRead)
495{
496 APIRET rc;
497
498 rc = DosRead(hFile, lpBuffer, size, nrBytesRead);
499 SetLastError(error2WinError(rc));
500 return (rc == NO_ERROR);
501}
502//******************************************************************************
503//******************************************************************************
504BOOL OSLibDosWrite(DWORD hFile, LPVOID lpBuffer, DWORD size, DWORD *nrBytesWritten)
505{
506 APIRET rc;
507
508 rc = DosWrite(hFile, lpBuffer, size, nrBytesWritten);
509 SetLastError(error2WinError(rc));
510 return (rc == NO_ERROR);
511}
512//******************************************************************************
513//******************************************************************************
514DWORD OSLibDosSetFilePtr(DWORD hFile, DWORD offset, DWORD method)
515{
516 DWORD os2method;
517 DWORD newoffset;
518 APIRET rc;
519
520 switch(method) {
521 case OSLIB_SETPTR_FILE_CURRENT:
522 os2method = FILE_CURRENT;
523 break;
524 case OSLIB_SETPTR_FILE_BEGIN:
525 os2method = FILE_BEGIN ;
526 break;
527 case OSLIB_SETPTR_FILE_END:
528 os2method = FILE_END;
529 break;
530 default:
531 return OSLIB_ERROR_INVALID_PARAMETER;
532 }
533 rc = DosSetFilePtr(hFile, offset, os2method, &newoffset);
534 if(rc) {
535 return -1;
536 }
537 else return newoffset;
538}
539//******************************************************************************
540//******************************************************************************
541BOOL OSLibDosDelete(char *lpszFileName)
542{
543 APIRET rc;
544
545 rc = DosDelete(lpszFileName);
546 if(rc) {
547 SetLastError(error2WinError(rc));
548 return FALSE;
549 }
550 return TRUE;
551}
552//******************************************************************************
553//******************************************************************************
554BOOL pmDateTimeToFileTime(FDATE *pDate,FTIME *pTime,FILETIME *pFT)
555{
556 USHORT dosTime, dosDate;
557
558 dosTime = *(USHORT*)pTime;
559 dosDate = *(USHORT*)pDate;
560
561 return DosDateTimeToFileTime(dosDate,dosTime,pFT);
562}
563//******************************************************************************
564//******************************************************************************
565#define NOT_NORMAL (FILE_ATTRIBUTE_READONLY_W | \
566 FILE_ATTRIBUTE_HIDDEN_W | \
567 FILE_ATTRIBUTE_SYSTEM_W | \
568 FILE_ATTRIBUTE_ARCHIVE_W)
569
570inline DWORD pm2WinFileAttributes(DWORD attrFile)
571{
572 DWORD res = 0;
573
574 if (!(attrFile & NOT_NORMAL))
575 res |= FILE_ATTRIBUTE_NORMAL_W;
576 if (attrFile & FILE_READONLY)
577 res |= FILE_ATTRIBUTE_READONLY_W;
578 if (attrFile & FILE_HIDDEN)
579 res |= FILE_ATTRIBUTE_HIDDEN_W;
580 if (attrFile & FILE_SYSTEM)
581 res |= FILE_ATTRIBUTE_SYSTEM_W;
582 if (attrFile & FILE_DIRECTORY)
583 res |= FILE_ATTRIBUTE_DIRECTORY_W;
584 if (attrFile & FILE_ARCHIVED)
585 res |= FILE_ATTRIBUTE_ARCHIVE_W;
586
587 //CB: not used: FILE_ATTRIBUTE_COMPRESSED_W
588
589 return res;
590}
591//******************************************************************************
592//******************************************************************************
593BOOL OSLibDosGetFileAttributesEx(PSZ pszName,
594 ULONG ulDummy,
595 PVOID pBuffer)
596{
597 APIRET rc; /* API return code */
598 FILESTATUS3 fs3; /* file information structure */
599 LPWIN32_FILE_ATTRIBUTE_DATA lpFad = (LPWIN32_FILE_ATTRIBUTE_DATA) pBuffer;
600
601 // Note: we only handle standard "GetFileExInfoStandard" requests
602 rc = DosQueryPathInfo(pszName, /* query the file information */
603 FIL_STANDARD,
604 &fs3,
605 sizeof(fs3));
606 if (rc != NO_ERROR) /* check for errors */
607 return FALSE; /* raise error condition */
608
609 // convert structure
610 lpFad->dwFileAttributes = pm2WinFileAttributes(fs3.attrFile);
611 pmDateTimeToFileTime(&fs3.fdateCreation, &fs3.ftimeCreation, &lpFad->ftCreationTime);
612 pmDateTimeToFileTime(&fs3.fdateLastAccess, &fs3.ftimeLastAccess, &lpFad->ftLastAccessTime);
613 pmDateTimeToFileTime(&fs3.fdateLastWrite, &fs3.ftimeLastWrite, &lpFad->ftLastWriteTime);
614
615 /* @@@PH we might add Aurora support ...
616 lpFad->nFileSizeHigh = info.nFileSizeHigh;
617 */
618 lpFad->nFileSizeHigh = 0;
619 lpFad->nFileSizeLow = fs3.cbFile;
620
621 return TRUE;
622}
623//******************************************************************************
624DWORD WIN32API GetEnvironmentVariableA(LPCSTR, LPSTR, DWORD );
625//******************************************************************************
626DWORD OSLibDosSearchPath(DWORD cmd, char *path, char *name, char *full_name,
627 DWORD length_fullname)
628{
629 switch(cmd) {
630 case OSLIB_SEARCHDIR:
631 if(DosSearchPath(SEARCH_IGNORENETERRS, path,
632 name, full_name, length_fullname) != 0) {
633 return 0;
634 }
635 return strlen(full_name);
636
637
638 case OSLIB_SEARCHCURDIR:
639 if(DosSearchPath(SEARCH_IGNORENETERRS | SEARCH_CUR_DIRECTORY, path,
640 name, full_name, length_fullname) != 0) {
641 return 0;
642 }
643 return strlen(full_name);
644
645 case OSLIB_SEARCHFILE:
646 {
647 FILESTATUS3 fileinfo;
648
649 if(DosQueryPathInfo(name, FIL_STANDARD, &fileinfo, sizeof(fileinfo)) != 0) {
650 return 0;
651 }
652 strncpy(full_name, name, length_fullname);
653 return strlen(full_name);
654 }
655
656 case OSLIB_SEARCHENV:
657 {
658 LPSTR envstring;
659 int envsize;
660 CHAR szResult[CCHMAXPATH];
661
662 envsize = GetEnvironmentVariableA(path, NULL, 0);
663 envstring = (LPSTR)malloc(envsize+1);
664 GetEnvironmentVariableA(path, envstring, envsize);
665 if(DosSearchPath(SEARCH_IGNORENETERRS, envstring,
666 name, szResult, sizeof(szResult)) != 0) {
667 free(envstring);
668 return 0;
669 }
670 free(envstring);
671 strcpy(full_name, szResult);
672 return strlen(full_name);
673 }
674 }
675 return 0;
676}
677//******************************************************************************
678//******************************************************************************
679APIRET OSLibDosQueryPathInfo(PSZ pszPathName,
680 ULONG ulInfoLevel,
681 PVOID pInfoBuf,
682 ULONG cbInfoBuf)
683{
684 APIRET rc = DosQueryPathInfo( pszPathName, ulInfoLevel,
685 pInfoBuf, cbInfoBuf );
686
687 if(rc == ERROR_TOO_MANY_OPEN_FILES)
688 {
689 LONG reqCount = 2;
690 ULONG maxFiles;
691
692 if(DosSetRelMaxFH(&reqCount, &maxFiles) == NO_ERROR)
693 rc = DosQueryPathInfo(pszPathName, ulInfoLevel,
694 pInfoBuf, cbInfoBuf );
695 }
696 return rc;
697}
698//******************************************************************************
699//******************************************************************************
700DWORD OSLibDosCreateFile(CHAR *lpszFile,
701 DWORD fuAccess,
702 DWORD fuShare,
703 LPSECURITY_ATTRIBUTES lpSecurityAttributes,
704 DWORD fuCreate,
705 DWORD fuAttrFlags,
706 HANDLE hTemplateFile)
707{
708 HFILE hFile;
709 ULONG actionTaken = 0;
710 ULONG fileSize = 0;
711 ULONG fileAttr = FILE_NORMAL;
712 ULONG openFlag = 0;
713 ULONG openMode = 0;
714 APIRET rc = ERROR_NOT_ENOUGH_MEMORY;;
715
716 //TODO: lpSecurityAttributes (inheritance)
717
718 if(fuAttrFlags & FILE_ATTRIBUTE_ARCHIVE_W)
719 fileAttr |= FILE_ARCHIVED;
720 if(fuAttrFlags & FILE_ATTRIBUTE_HIDDEN_W)
721 fileAttr |= FILE_HIDDEN;
722 if(fuAttrFlags & FILE_ATTRIBUTE_SYSTEM_W)
723 fileAttr |= FILE_SYSTEM;
724 if(fuAttrFlags & FILE_ATTRIBUTE_READONLY_W)
725 fileAttr |= FILE_READONLY;
726 // TODO: FILE_ATTRIBUTE_TEMPORARY_W
727
728 switch(fuCreate)
729 {
730 case CREATE_NEW_W:
731 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_FAIL_IF_EXISTS;
732 break;
733 case CREATE_ALWAYS_W:
734 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS;
735 break;
736 case OPEN_EXISTING_W:
737 openFlag |= OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
738 break;
739 case OPEN_ALWAYS_W:
740 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
741 break;
742 case TRUNCATE_EXISTING_W:
743 openFlag |= OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS;
744 break;
745 }
746
747 if(fuAttrFlags & FILE_FLAG_WRITE_THROUGH_W) openMode |= OPEN_FLAGS_WRITE_THROUGH;
748 if(fuAttrFlags & FILE_FLAG_NO_BUFFERING_W) openMode |= OPEN_FLAGS_NO_CACHE;
749 if(fuAttrFlags & FILE_FLAG_RANDOM_ACCESS_W) openMode |= OPEN_FLAGS_RANDOM;
750 if(fuAttrFlags & FILE_FLAG_SEQUENTIAL_SCAN_W) openMode |= OPEN_FLAGS_SEQUENTIAL;
751 // TODO: FILE_FLAG_BACKUP_SEMANTICS_W
752 // FILE_FLAG_POSIX_SEMANTICS_W are not supported
753
754 if(fuShare == 0)
755 openMode |= OPEN_SHARE_DENYREADWRITE;
756 else
757 if(fuShare == (FILE_SHARE_READ_W | FILE_SHARE_WRITE_W))
758 openMode |= OPEN_SHARE_DENYNONE;
759 else
760 if(fuShare & FILE_SHARE_READ_W)
761 openMode |= OPEN_SHARE_DENYWRITE;
762 else
763 if(fuShare & FILE_SHARE_WRITE_W)
764 openMode |= OPEN_SHARE_DENYREAD;
765
766 if(fuAccess == (GENERIC_READ_W | GENERIC_WRITE_W))
767 openMode |= OPEN_ACCESS_READWRITE;
768 else
769 if(fuAccess & GENERIC_READ_W)
770 openMode |= OPEN_ACCESS_READONLY;
771 else
772 if(fuAccess & GENERIC_WRITE_W)
773 openMode |= OPEN_ACCESS_WRITEONLY;
774
775 int retry = 0;
776 while(retry < 2)
777 {
778 rc = DosOpen((PSZ)lpszFile,
779 &hFile,
780 &actionTaken,
781 fileSize,
782 fileAttr,
783 openFlag,
784 openMode,
785 NULL);
786 if(rc == ERROR_TOO_MANY_OPEN_FILES)
787 {
788 ULONG CurMaxFH;
789 LONG ReqCount = 32;
790
791 rc = DosSetRelMaxFH(&ReqCount, &CurMaxFH);
792 if(rc) {
793 dprintf(("DosSetRelMaxFH returned %d", rc));
794 SetLastError(ERROR_TOO_MANY_OPEN_FILES_W);
795 return INVALID_HANDLE_VALUE_W;
796 }
797 dprintf(("DosOpen failed -> increased nr open files to %d", CurMaxFH));
798 }
799 else break;
800 retry++;
801 }
802
803 if(rc)
804 {
805 SetLastError(error2WinError(rc));
806 return INVALID_HANDLE_VALUE_W;
807 }
808 SetLastError(ERROR_SUCCESS_W);
809 return hFile;
810}
811//******************************************************************************
812//******************************************************************************
813DWORD OSLibDosOpenFile(CHAR *lpszFile, UINT fuMode)
814{
815 ULONG actionTaken = 0;
816 ULONG fileSize = 0;
817 ULONG fileAttr = FILE_NORMAL;
818 ULONG openFlag = 0;
819 ULONG openMode = 0;
820 APIRET rc = ERROR_NOT_ENOUGH_MEMORY;
821 HFILE hFile;
822
823 if(!(fuMode & (OF_CREATE_W | OF_READWRITE_W | OF_WRITE_W)))
824 {
825 openMode |= OPEN_ACCESS_READONLY;
826 openFlag |= OPEN_ACTION_OPEN_IF_EXISTS;
827 }
828 else
829 {
830 if(fuMode & OF_CREATE_W) {
831 openFlag |= OPEN_ACTION_CREATE_IF_NEW |
832 OPEN_ACTION_REPLACE_IF_EXISTS;
833 }
834 else openFlag |= OPEN_ACTION_OPEN_IF_EXISTS; //180575
835
836 if(fuMode & OF_READWRITE_W)
837 openMode |= OPEN_ACCESS_READWRITE;
838 else
839 if(fuMode & OF_WRITE_W)
840 openMode |= OPEN_ACCESS_WRITEONLY;
841 else
842 if(fuMode & OF_CREATE_W)
843 openMode |= OPEN_ACCESS_READWRITE;
844 }
845
846 if((fuMode & OF_SHARE_DENY_WRITE_W) ||
847 !(fuMode & (OF_SHARE_DENY_READ_W | OF_SHARE_DENY_NONE_W | OF_SHARE_EXCLUSIVE_W)))
848 openMode |= OPEN_SHARE_DENYWRITE;
849 else
850 if (fuMode & OF_SHARE_DENY_NONE_W)
851 openMode |= OPEN_SHARE_DENYNONE;
852 else
853 if (fuMode & OF_SHARE_DENY_READ_W)
854 openMode |= OPEN_SHARE_DENYREAD;
855 else
856 if (fuMode & OF_SHARE_EXCLUSIVE_W)
857 openMode |= OPEN_SHARE_DENYREADWRITE;
858
859 rc = DosOpen((PSZ)lpszFile,
860 &hFile,
861 &actionTaken,
862 fileSize,
863 fileAttr,
864 openFlag,
865 openMode,
866 NULL);
867
868 if(rc != NO_ERROR)
869 {
870 if(fuMode & OF_EXIST_W)
871 {
872 if(rc == ERROR_OPEN_FAILED || rc == ERROR_FILE_NOT_FOUND)
873 {
874 SetLastError(ERROR_FILE_NOT_FOUND_W);
875 return HFILE_ERROR_W;
876 }
877 }
878 if((rc == ERROR_OPEN_FAILED) && (openFlag & OPEN_ACTION_OPEN_IF_EXISTS))
879 {
880 SetLastError(ERROR_FILE_NOT_FOUND_W);
881 }
882 else SetLastError(error2WinError(rc));
883
884 return HFILE_ERROR_W;
885 }
886 SetLastError(ERROR_SUCCESS_W);
887 return hFile;
888}
889//******************************************************************************
890//******************************************************************************
891BOOL OSLibDosLockFile(DWORD hFile, DWORD dwFlags,
892 DWORD OffsetLow, DWORD OffsetHigh,
893 DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh,
894 LPOVERLAPPED lpOverlapped)
895{
896 APIRET rc;
897
898 // Set 5 secs timeout for locking file and no other can access this
899 // file region
900
901 if(lpOverlapped) {//TODO:
902 dprintf(("OSLibDosLockFile: overlapped lock not yet implemented!!"));
903 }
904 //TODO: Locking region crossing end of file is permitted. Works in OS/2??
905 if(f64BitIO)
906 {
907 FILELOCKL lockRangeL;
908
909 lockRangeL.lOffset.ulLo = OffsetLow;
910 lockRangeL.lOffset.ulHi = OffsetHigh;
911 lockRangeL.lRange.ulLo = nNumberOfBytesToLockLow;
912 lockRangeL.lRange.ulHi = nNumberOfBytesToLockHigh;
913
914 rc = OdinDosSetFileLocksL(hFile, NULL, &lockRangeL,
915 (dwFlags & LOCKFILE_FAIL_IMMEDIATELY_W) ? 0 : 5000, 0);
916 }
917 else
918 {
919 FILELOCK lockRange = { OffsetLow, nNumberOfBytesToLockLow };
920
921 rc = DosSetFileLocks(hFile, NULL, &lockRange,
922 (dwFlags & LOCKFILE_FAIL_IMMEDIATELY_W) ? 0 : 5000, 0);
923 }
924 if(rc) {
925 SetLastError(error2WinError(rc));
926 return FALSE;
927 }
928 SetLastError(ERROR_SUCCESS_W);
929 return TRUE;
930}
931//******************************************************************************
932//******************************************************************************
933BOOL OSLibDosUnlockFile(DWORD hFile, DWORD OffsetLow, DWORD OffsetHigh,
934 DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh,
935 LPOVERLAPPED lpOverlapped)
936{
937 APIRET rc;
938
939 // Set 5 secs timeout for unlocking file and no other can access this
940 // file region
941
942 if(lpOverlapped) {//TODO:
943 dprintf(("OSLibDosUnlockFile: overlapped unlock not yet implemented!!"));
944 }
945 if(f64BitIO)
946 {
947 FILELOCKL unlockRangeL;
948
949 unlockRangeL.lOffset.ulLo = OffsetLow;
950 unlockRangeL.lOffset.ulHi = OffsetHigh;
951 unlockRangeL.lRange.ulLo = nNumberOfBytesToLockLow;
952 unlockRangeL.lRange.ulHi = nNumberOfBytesToLockHigh;
953
954 rc = OdinDosSetFileLocksL(hFile, &unlockRangeL, NULL, 5000, 0);
955 }
956 else
957 {
958 FILELOCK unlockRange = { OffsetLow, nNumberOfBytesToLockLow };
959
960 rc = DosSetFileLocks(hFile, &unlockRange, NULL, 5000, 0);
961 }
962 if(rc) {
963 SetLastError(error2WinError(rc));
964 return FALSE;
965 }
966 SetLastError(ERROR_SUCCESS_W);
967 return TRUE;
968}
969//******************************************************************************
970//******************************************************************************
971BOOL OSLibDosFlushFileBuffers(DWORD hFile)
972{
973 APIRET rc;
974
975 rc = DosResetBuffer(hFile);
976 SetLastError(error2WinError(rc));
977 return (rc == NO_ERROR);
978}
979//******************************************************************************
980//******************************************************************************
981DWORD OSLibDosGetFileSize(DWORD hFile, LPDWORD lpdwFileSizeHigh)
982{
983 APIRET rc;
984 ULONG sizeLow;
985
986 if(f64BitIO)
987 {
988 FILESTATUS3L fsts3ConfigInfoL = {{0}};
989 ULONG ulBufSize = sizeof(FILESTATUS3L);
990
991 rc = DosQueryFileInfo(hFile, FIL_STANDARDL, &fsts3ConfigInfoL, ulBufSize);
992 if(lpdwFileSizeHigh) {
993 *lpdwFileSizeHigh = fsts3ConfigInfoL.cbFile.ulHi;
994 }
995 sizeLow = fsts3ConfigInfoL.cbFile.ulLo;
996 }
997 else
998 {
999 FILESTATUS3 fsts3ConfigInfo = {{0}};
1000 ULONG ulBufSize = sizeof(FILESTATUS3);
1001
1002 if(lpdwFileSizeHigh) {
1003 *lpdwFileSizeHigh = 0;
1004 }
1005 rc = DosQueryFileInfo(hFile, FIL_STANDARD, &fsts3ConfigInfo, ulBufSize);
1006 sizeLow = fsts3ConfigInfo.cbFile;
1007 }
1008 if(rc) {
1009 SetLastError(error2WinError(rc));
1010 return -1;
1011 }
1012 SetLastError(ERROR_SUCCESS_W);
1013 return sizeLow;
1014}
1015//******************************************************************************
1016//******************************************************************************
1017DWORD OSLibDosSetFilePointer(DWORD hFile, DWORD OffsetLow, DWORD *OffsetHigh, DWORD method)
1018{
1019 LONGLONG offsetL;
1020 LONGLONG newoffsetL;
1021 APIRET rc;
1022 DWORD newoffset;
1023
1024 switch(method) {
1025 case FILE_BEGIN_W:
1026 method = FILE_BEGIN;
1027 break;
1028
1029 case FILE_CURRENT_W:
1030 method = FILE_CURRENT;
1031 break;
1032
1033 case FILE_END_W:
1034 method = FILE_END;
1035 break;
1036 }
1037 if(f64BitIO) {
1038 offsetL.ulLo = OffsetLow;
1039 offsetL.ulHi = (OffsetHigh) ? *OffsetHigh : 0;
1040 rc = OdinDosSetFilePtrL(hFile, offsetL, method, &newoffsetL);
1041 if(OffsetHigh) {
1042 *OffsetHigh = newoffsetL.ulHi;
1043 }
1044 newoffset = newoffsetL.ulLo;
1045 }
1046 else rc = DosSetFilePtr(hFile, OffsetLow, method, &newoffset);
1047 if(rc) {
1048 SetLastError(error2WinError(rc));
1049 return -1;
1050 }
1051 SetLastError(ERROR_SUCCESS_W);
1052 return newoffset;
1053}
1054//******************************************************************************
1055//******************************************************************************
1056BOOL OSLibDosSetEndOfFile(DWORD hFile)
1057{
1058 ULONG newFilePos;
1059 LONGLONG FilePosL = {0,0};
1060 LONGLONG newFilePosL;
1061 APIRET rc;
1062
1063 if(f64BitIO) {
1064 rc = OdinDosSetFilePtrL(hFile, FilePosL, FILE_CURRENT, &newFilePosL);
1065 if(rc == 0) {
1066 rc = OdinDosSetFileSizeL(hFile, newFilePosL);
1067 }
1068 }
1069 else {
1070 rc = DosSetFilePtr(hFile, 0, FILE_CURRENT, &newFilePos);
1071 if(rc == 0) {
1072 rc = DosSetFileSize(hFile, newFilePos);
1073 }
1074 }
1075 if(rc) {
1076 SetLastError(error2WinError(rc));
1077 return FALSE;
1078 }
1079 SetLastError(ERROR_SUCCESS_W);
1080 return TRUE;
1081}
1082//******************************************************************************
1083//******************************************************************************
1084BOOL OSLibDosGetFileInformationByHandle(DWORD hFile, BY_HANDLE_FILE_INFORMATION* pInfo)
1085{
1086 APIRET rc;
1087
1088 if(f64BitIO)
1089 {
1090 FILESTATUS4L statusL = { 0 };
1091
1092 rc = DosQueryFileInfo(hFile,
1093 FIL_QUERYEASIZEL,
1094 &statusL,
1095 sizeof(statusL));
1096 if(rc == NO_ERROR)
1097 {
1098 pInfo->dwFileAttributes = 0;
1099 if(!(statusL.attrFile & NOT_NORMAL))
1100 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_NORMAL_W;
1101 if(statusL.attrFile & FILE_READONLY)
1102 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_READONLY_W;
1103 if(statusL.attrFile & FILE_HIDDEN)
1104 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN_W;
1105 if(statusL.attrFile & FILE_SYSTEM)
1106 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_SYSTEM_W;
1107 if(statusL.attrFile & FILE_DIRECTORY)
1108 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY_W;
1109 if(statusL.attrFile & FILE_ARCHIVED)
1110 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_ARCHIVE_W;
1111
1112 pmDateTimeToFileTime(&statusL.fdateCreation,
1113 &statusL.ftimeCreation,
1114 &pInfo->ftCreationTime);
1115 pmDateTimeToFileTime(&statusL.fdateLastAccess,
1116 &statusL.ftimeLastAccess,
1117 &pInfo->ftLastAccessTime);
1118 pmDateTimeToFileTime(&statusL.fdateLastWrite,
1119 &statusL.ftimeLastWrite,
1120 &pInfo->ftLastWriteTime);
1121
1122 pInfo->nFileSizeHigh = statusL.cbFile.ulHi;
1123 pInfo->nFileSizeLow = statusL.cbFile.ulLo;
1124 pInfo->dwVolumeSerialNumber = 0; //todo
1125 pInfo->nNumberOfLinks = 1;
1126 pInfo->nFileIndexHigh = 0;
1127 pInfo->nFileIndexLow = 0;
1128 }
1129 }
1130 else
1131 {
1132 FILESTATUS4 status = { 0 };
1133
1134 rc = DosQueryFileInfo(hFile,
1135 FIL_QUERYEASIZE,
1136 &status,
1137 sizeof(status));
1138 if(rc == NO_ERROR)
1139 {
1140 pInfo->dwFileAttributes = 0;
1141 if(!(status.attrFile & NOT_NORMAL))
1142 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_NORMAL_W;
1143 if(status.attrFile & FILE_READONLY)
1144 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_READONLY_W;
1145 if(status.attrFile & FILE_HIDDEN)
1146 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN_W;
1147 if(status.attrFile & FILE_SYSTEM)
1148 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_SYSTEM_W;
1149 if(status.attrFile & FILE_DIRECTORY)
1150 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY_W;
1151 if(status.attrFile & FILE_ARCHIVED)
1152 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_ARCHIVE_W;
1153
1154 pmDateTimeToFileTime(&status.fdateCreation,
1155 &status.ftimeCreation,
1156 &pInfo->ftCreationTime);
1157 pmDateTimeToFileTime(&status.fdateLastAccess,
1158 &status.ftimeLastAccess,
1159 &pInfo->ftLastAccessTime);
1160 pmDateTimeToFileTime(&status.fdateLastWrite,
1161 &status.ftimeLastWrite,
1162 &pInfo->ftLastWriteTime);
1163
1164 pInfo->nFileSizeHigh = 0;
1165 pInfo->nFileSizeLow = status.cbFile;
1166 pInfo->dwVolumeSerialNumber = 0; //todo
1167 pInfo->nNumberOfLinks = 1;
1168 pInfo->nFileIndexHigh = 0;
1169 pInfo->nFileIndexLow = 0;
1170 }
1171 }
1172 if(rc) {
1173 SetLastError(error2WinError(rc));
1174 return FALSE;
1175 }
1176 SetLastError(ERROR_SUCCESS_W);
1177 return TRUE;
1178}
1179//******************************************************************************
1180//******************************************************************************
1181BOOL OSLibDosSetFileTime(DWORD hFile, WORD creationdate, WORD creationtime,
1182 WORD lastaccessdate, WORD lastaccesstime,
1183 WORD lastwritedate, WORD lastwritetime)
1184{
1185 FILESTATUS3 fileInfo;
1186 APIRET rc;
1187
1188 rc = DosQueryFileInfo(hFile, FIL_STANDARD, &fileInfo, sizeof(fileInfo));
1189
1190 if(rc == NO_ERROR)
1191 {
1192 if(creationdate && creationtime) {
1193 fileInfo.fdateCreation = *(FDATE *)&creationdate;
1194 fileInfo.ftimeCreation = *(FTIME *)&creationtime;
1195 }
1196 if(lastaccessdate && lastaccesstime) {
1197 fileInfo.fdateLastAccess = *(FDATE *)&lastaccessdate;
1198 fileInfo.ftimeLastAccess = *(FTIME *)&lastaccesstime;
1199 }
1200 if(lastwritedate && lastwritetime) {
1201 fileInfo.fdateLastWrite = *(FDATE *)&lastwritedate;
1202 fileInfo.ftimeLastWrite = *(FTIME *)&lastwritetime;
1203 }
1204
1205 rc = DosSetFileInfo(hFile, FIL_STANDARD, &fileInfo, sizeof(fileInfo));
1206 }
1207
1208 if(rc)
1209 {
1210 SetLastError(error2WinError(rc));
1211 return FALSE;
1212 }
1213 SetLastError(ERROR_SUCCESS_W);
1214 return TRUE;
1215}
1216//******************************************************************************
1217//******************************************************************************
1218BOOL OSLibDosGetFileTime(DWORD hFile, WORD *creationdate, WORD *creationtime,
1219 WORD *lastaccessdate, WORD *lastaccesstime,
1220 WORD *lastwritedate, WORD *lastwritetime)
1221{
1222 FILESTATUS3 fileInfo;
1223 APIRET rc;
1224
1225 rc = DosQueryFileInfo(hFile, FIL_STANDARD, &fileInfo, sizeof(fileInfo));
1226
1227 if(rc == NO_ERROR)
1228 {
1229 *creationdate = *(WORD *)&fileInfo.fdateCreation;
1230 *creationtime = *(WORD *)&fileInfo.ftimeCreation;
1231 *lastaccessdate = *(WORD *)&fileInfo.fdateLastAccess;
1232 *lastaccesstime = *(WORD *)&fileInfo.ftimeLastAccess;
1233 *lastwritedate = *(WORD *)&fileInfo.fdateLastWrite;
1234 *lastwritetime = *(WORD *)&fileInfo.ftimeLastWrite;
1235 }
1236
1237 if(rc)
1238 {
1239 SetLastError(error2WinError(rc));
1240 return FALSE;
1241 }
1242 SetLastError(ERROR_SUCCESS_W);
1243 return TRUE;
1244}
1245//******************************************************************************
1246//******************************************************************************
1247DWORD OSLibDosSetFilePtr2(DWORD hFile, DWORD offset, DWORD method)
1248{
1249 DWORD newoffset;
1250 APIRET rc;
1251
1252
1253 rc = DosSetFilePtr(hFile, offset, method, &newoffset);
1254 if(rc) {
1255 dprintf(("DosSetFilePtr Error rc:%d", rc));
1256 return -1;
1257 }
1258 else return newoffset;
1259}
1260//******************************************************************************
1261//******************************************************************************
1262DWORD OSLibDosDupHandle(DWORD hFile, DWORD *hNew)
1263{
1264 *hNew = -1;
1265 return DosDupHandle(hFile, hNew);
1266}
1267//******************************************************************************
1268//******************************************************************************
1269void OSLibDosDisableHardError(BOOL fTurnOff)
1270{
1271 DosError((fTurnOff) ? FERR_DISABLEHARDERR : FERR_ENABLEHARDERR);
1272}
1273//******************************************************************************
1274//Returns time spent in kernel & user mode in milliseconds
1275//******************************************************************************
1276BOOL OSLibDosQueryProcTimes(DWORD procid, ULONG *kerneltime, ULONG *usertime)
1277{
1278 APIRET rc;
1279 char *buf;
1280 ULONG size;
1281 ULONG nrthreads = 4;
1282
1283tryagain:
1284 size = sizeof(QTOPLEVEL)+sizeof(QGLOBAL)+sizeof(QPROCESS) + nrthreads*sizeof(QTHREAD);
1285 buf = (char *)malloc(size);
1286 rc = DosQuerySysState(0x1, RESERVED, procid, RESERVED, (PCHAR)buf, size);
1287
1288 if(rc) {
1289 free(buf);
1290 if(rc == ERROR_BUFFER_OVERFLOW) {
1291 nrthreads += 4;
1292 goto tryagain;
1293 }
1294 return FALSE;
1295 }
1296 PQTOPLEVEL top = (PQTOPLEVEL)buf;
1297
1298 *kerneltime = 0;
1299 *usertime = 0;
1300 for(int i=0;i<top->procdata->threadcnt;i++) {
1301 *kerneltime += top->procdata->threads[i].systime;
1302 *usertime += top->procdata->threads[i].usertime;
1303 }
1304 free(buf);
1305 return TRUE;
1306}
1307//******************************************************************************
1308//******************************************************************************
1309// TODO: implement SecurityAttributes parameter
1310DWORD OSLibDosCreateNamedPipe(LPCTSTR lpName,
1311 DWORD dwOpenMode,
1312 DWORD dwPipeMode,
1313 DWORD nMaxInstances,
1314 DWORD nOutBufferSize,
1315 DWORD nInBufferSize,
1316 DWORD nDefaultTimeOut,
1317 void* lpSecurityAttributes)
1318{ DWORD dwOS2Mode = 0;
1319 DWORD dwOS2PipeMode = 0;
1320 LPSTR lpOS2Name;
1321 DWORD hPipe;
1322 DWORD rc;
1323
1324 if (dwOpenMode & PIPE_ACCESS_DUPLEX_W)
1325 dwOS2Mode |= NP_ACCESS_DUPLEX;
1326 else
1327 if (dwOpenMode & PIPE_ACCESS_INBOUND_W)
1328 dwOS2Mode |= NP_ACCESS_INBOUND;
1329 else
1330 if (dwOpenMode & PIPE_ACCESS_OUTBOUND_W)
1331 dwOS2Mode |= NP_ACCESS_OUTBOUND;
1332 // TODO:
1333 // if(dwOpenMode & FILE_FLAG_OVERLAPPED)
1334 // if(dwOpenMode & WRITE_DAC)
1335 // if(dwOpenMode & WRITE_OWNER)
1336 // if(dwOpenMode & ACCESS_SYSTEM_SECURITY)
1337 if(dwOpenMode & FILE_FLAG_WRITE_THROUGH_W)
1338 dwOS2Mode |= NP_WRITEBEHIND; // FIXME: I'm not sure!
1339
1340 if (dwPipeMode & PIPE_WAIT_W)
1341 dwOS2PipeMode |= NP_WAIT;
1342 if (dwPipeMode & PIPE_NOWAIT_W)
1343 dwOS2PipeMode |= NP_NOWAIT;
1344 if (dwPipeMode & PIPE_READMODE_BYTE_W)
1345 dwOS2PipeMode |= NP_READMODE_BYTE;
1346 if (dwPipeMode & PIPE_READMODE_MESSAGE_W)
1347 dwOS2PipeMode |= NP_READMODE_MESSAGE;
1348 if (dwPipeMode & PIPE_TYPE_BYTE_W)
1349 dwOS2PipeMode |= NP_TYPE_BYTE;
1350 if (dwPipeMode & PIPE_TYPE_MESSAGE_W)
1351 dwOS2PipeMode |= NP_TYPE_MESSAGE;
1352
1353 if (nMaxInstances>0xff)
1354 {
1355 SetLastError(ERROR_INVALID_PARAMETER_W); // ERROR_INVALID_PARAMETER
1356 return -1; // INVALID_HANDLE_VALUE
1357 }
1358 dwOS2PipeMode |= nMaxInstances;
1359
1360 if (strstr(lpName,"\\\\."))
1361 {
1362 // If pipe is created on the local machine
1363 // we must delete string \\. because
1364 // in Windows named pipes scheme is a \\.\PIPE\pipename
1365 // but in OS/2 only \PIPE\pipename
1366 lpOS2Name = (LPSTR)lpName + 3;
1367 }
1368 else lpOS2Name = (LPSTR)lpName;
1369
1370 dprintf(("DosCreateNPipe(%s,%x,%x,%x,%x,%x)",lpOS2Name,dwOS2Mode,dwOS2PipeMode,nInBufferSize,nOutBufferSize,nDefaultTimeOut));
1371 rc=DosCreateNPipe(lpOS2Name,
1372 &hPipe,
1373 dwOS2Mode,
1374 dwOS2PipeMode,
1375 nInBufferSize,
1376 nInBufferSize,
1377 nDefaultTimeOut); // Timeouts must be tested!
1378
1379 dprintf(("DosCreateNPipe rc=%d",rc));
1380 if (rc)
1381 {
1382 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER_W));
1383 return -1; // INVALID_HANDLE_VALUE
1384 }
1385 return hPipe;
1386}
1387
1388//******************************************************************************
1389//******************************************************************************
1390// TODO: implement lpOverlapped parameter!
1391BOOL OSLibDosConnectNamedPipe(DWORD hNamedPipe, LPOVERLAPPED lpOverlapped)
1392{
1393 DWORD rc;
1394
1395 rc=DosConnectNPipe(hNamedPipe);
1396 dprintf(("DosConnectNPipe rc=%d",rc));
1397
1398 if (!rc) return (TRUE);
1399 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1400
1401 return (FALSE);
1402}
1403
1404//******************************************************************************
1405//******************************************************************************
1406BOOL OSLibDosCallNamedPipe( LPCTSTR lpNamedPipeName,
1407 LPVOID lpInBuffer,
1408 DWORD nInBufferSize,
1409 LPVOID lpOutBuffer,
1410 DWORD nOutBufferSize,
1411 LPDWORD lpBytesRead,
1412 DWORD nTimeOut )
1413{
1414 LPSTR lpOS2Name;
1415 DWORD rc;
1416
1417 if (strstr(lpNamedPipeName,"\\\\."))
1418 {
1419 // If pipe is created on the local machine
1420 // we must delete string \\. because
1421 // in Windows named pipes scheme is a \\.\PIPE\pipename
1422 // but in OS/2 only \PIPE\pipename
1423 lpOS2Name = (LPSTR)lpNamedPipeName + 3;
1424 }
1425 else lpOS2Name = (LPSTR)lpNamedPipeName;
1426
1427 rc=DosCallNPipe(lpOS2Name,
1428 lpInBuffer,
1429 nInBufferSize,
1430 lpOutBuffer,
1431 nOutBufferSize,
1432 lpBytesRead,
1433 nTimeOut );
1434
1435
1436 if (!rc) return (TRUE);
1437 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1438
1439 return (FALSE);
1440}
1441
1442//******************************************************************************
1443//******************************************************************************
1444BOOL OSLibDosTransactNamedPipe( DWORD hNamedPipe,
1445 LPVOID lpInBuffer,
1446 DWORD nInBufferSize,
1447 LPVOID lpOutBuffer,
1448 DWORD nOutBufferSize,
1449 LPDWORD lpBytesRead,
1450 LPOVERLAPPED lpOverlapped)
1451{
1452 DWORD rc;
1453
1454 rc=DosTransactNPipe(hNamedPipe,
1455 lpOutBuffer,
1456 nOutBufferSize,
1457 lpInBuffer,
1458 nInBufferSize,
1459 lpBytesRead);
1460
1461 dprintf(("DosTransactNPipe returned rc=%d");)
1462 if (!rc) return (TRUE);
1463 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1464
1465 return (FALSE);
1466}
1467
1468//******************************************************************************
1469//******************************************************************************
1470BOOL OSLibDosPeekNamedPipe(DWORD hPipe,
1471 LPVOID lpvBuffer,
1472 DWORD cbBuffer,
1473 LPDWORD lpcbRead,
1474 LPDWORD lpcbAvail,
1475 LPDWORD lpcbMessage)
1476{
1477 DWORD rc;
1478 AVAILDATA availData ={0};
1479 ULONG ulDummy;
1480
1481 rc=DosPeekNPipe(hPipe,lpvBuffer,cbBuffer,lpcbRead,&availData,&ulDummy);
1482
1483 dprintf(("DosPeekNPipe returned rc=%d",rc));
1484
1485 if (!rc)
1486 {
1487 *lpcbAvail = availData.cbpipe;
1488 *lpcbMessage = availData.cbmessage;
1489 return (TRUE);
1490 }
1491 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1492
1493 return (FALSE);
1494}
1495//******************************************************************************
1496//******************************************************************************
1497BOOL OSLibDosDisconnectNamedPipe(DWORD hPipe)
1498{
1499 DWORD rc;
1500
1501 rc=DosDisConnectNPipe(hPipe);
1502
1503 dprintf(("DosDisConnectNPipe returned rc=%d",rc));
1504
1505 if (!rc) return TRUE;
1506 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1507
1508 return (FALSE);
1509}
1510//******************************************************************************
1511//******************************************************************************
1512BOOL OSLibDosWaitNamedPipe(LPCSTR lpszNamedPipeName,
1513 DWORD dwTimeout)
1514{
1515 LPSTR lpOS2Name;
1516 DWORD rc;
1517
1518 if (strstr(lpszNamedPipeName,"\\\\."))
1519 {
1520 // If pipe is created on the local machine
1521 // we must delete string \\. because
1522 // in Windows named pipes scheme is a \\.\PIPE\pipename
1523 // but in OS/2 only \PIPE\pipename
1524 lpOS2Name = (LPSTR)lpszNamedPipeName + 3;
1525 }
1526 else lpOS2Name = (LPSTR)lpszNamedPipeName;
1527
1528 rc=DosWaitNPipe(lpOS2Name,dwTimeout);
1529
1530 dprintf(("DosWaitNPipe returned rc=%d",rc));
1531
1532 if (!rc) return TRUE;
1533 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1534
1535 return (FALSE);
1536}
1537//******************************************************************************
1538//******************************************************************************
1539BOOL isRoot(CHAR* name)
1540{
1541 if (name[1] == ':')
1542 {
1543 //local name (x:\)
1544 return (name[2] == 0) || !strchr(&name[3],'\\');
1545 } else if (name[0] == '\\')
1546 {
1547 //UNC name (\\resource\drive\)
1548 CHAR *drive,*dir;
1549
1550 drive = strchr(&name[2],'\\');
1551 if (!drive) return FALSE;
1552 dir = strchr(&drive[1],'\\');
1553 if (!dir) return TRUE;
1554 return !strchr(&dir[1],'\\');
1555 } else return FALSE; //unknown
1556}
1557//******************************************************************************
1558//******************************************************************************
1559inline CHAR system2DOSCharacter(CHAR ch)
1560{
1561 switch(ch)
1562 {
1563 case ' ':
1564 case '.':
1565 case '~':
1566 return '_';
1567
1568 default:
1569 return toupper(ch);
1570 }
1571}
1572
1573VOID long2ShortName(CHAR* longName,CHAR* shortName)
1574{
1575 INT x;
1576 CHAR *source = longName,*dest = shortName,*ext = strrchr(longName,'.');
1577
1578 if ((strcmp(longName,".") == 0) || (strcmp(longName,"..") == 0))
1579 {
1580 strcpy(shortName,longName);
1581 return;
1582 }
1583
1584 //CB: quick and dirty, real FILE~12.EXT is too slow
1585
1586 //8 character file name
1587 for (x = 0;x < 8;x++)
1588 {
1589 if ((source == ext) || (source[0] == 0)) break;
1590 dest[0] = system2DOSCharacter(source[0]);
1591 source++;
1592 dest++;
1593 }
1594
1595 if (source[0] == 0)
1596 {
1597 dest[0] = 0;
1598 return;
1599 }
1600
1601 if (source != ext)
1602 {
1603 //longName > 8 characters, insert ~1
1604 shortName[6] = '~';
1605 shortName[7] = '1';
1606 }
1607
1608 if (ext)
1609 {
1610 //add extension, 3 characters
1611 dest[0] = ext[0];
1612 dest++;
1613 ext++;
1614 for (x = 0;x < 3;x++)
1615 {
1616 if (ext[0] == 0) break;
1617 dest[0] = system2DOSCharacter(ext[0]);
1618 ext++;
1619 dest++;
1620 }
1621 }
1622 dest[0] = 0;
1623}
1624//******************************************************************************
1625//******************************************************************************
1626VOID translateFileResults(FILESTATUS3 *pResult,LPWIN32_FIND_DATAA pFind,CHAR* achName)
1627{
1628 CHAR* name;
1629
1630 pFind->dwFileAttributes = pm2WinFileAttributes(pResult->attrFile);
1631
1632 pmDateTimeToFileTime(&pResult->fdateCreation,&pResult->ftimeCreation,&pFind->ftCreationTime);
1633 pmDateTimeToFileTime(&pResult->fdateLastAccess,&pResult->ftimeLastAccess,&pFind->ftLastAccessTime);
1634 pmDateTimeToFileTime(&pResult->fdateLastWrite,&pResult->ftimeLastWrite,&pFind->ftLastWriteTime);
1635
1636 pFind->nFileSizeHigh = 0; //CB: fixme
1637 pFind->nFileSizeLow = pResult->cbFile;
1638 name = strrchr(achName,'\\');
1639 if (name)
1640 {
1641 name++;
1642 strcpy(pFind->cFileName,name);
1643 } else pFind->cFileName[0] = 0;
1644 long2ShortName(pFind->cFileName,pFind->cAlternateFileName);
1645}
1646
1647VOID translateFindResults(FILEFINDBUF3 *pResult,LPWIN32_FIND_DATAA pFind)
1648{
1649 pFind->dwFileAttributes = pm2WinFileAttributes(pResult->attrFile);
1650
1651 pmDateTimeToFileTime(&pResult->fdateCreation,&pResult->ftimeCreation,&pFind->ftCreationTime);
1652 pmDateTimeToFileTime(&pResult->fdateLastAccess,&pResult->ftimeLastAccess,&pFind->ftLastAccessTime);
1653 pmDateTimeToFileTime(&pResult->fdateLastWrite,&pResult->ftimeLastWrite,&pFind->ftLastWriteTime);
1654
1655 pFind->nFileSizeHigh = 0; //CB: fixme
1656 pFind->nFileSizeLow = pResult->cbFile;
1657 strcpy(pFind->cFileName,pResult->achName);
1658 long2ShortName(pFind->cFileName,pFind->cAlternateFileName);
1659}
1660//******************************************************************************
1661//******************************************************************************
1662DWORD OSLibDosFindFirst(LPCSTR lpFileName,WIN32_FIND_DATAA* lpFindFileData)
1663{
1664 HDIR hDir = -1;
1665 ULONG attrs;
1666 FILEFINDBUF3 result;
1667 ULONG searchCount = 1;
1668
1669 attrs = FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY | FILE_ARCHIVED;
1670 result.achName[0] = 0;
1671
1672 DosError(FERR_DISABLEHARDERR | FERR_DISABLEEXCEPTION);
1673 APIRET rc = DosFindFirst((PSZ)lpFileName,&hDir,attrs,&result,sizeof(result),&searchCount,FIL_STANDARD);
1674 DosError(FERR_ENABLEHARDERR | FERR_ENABLEEXCEPTION);
1675
1676 //check root: skip "." and ".." (HPFS, not on FAT)
1677 //check in OSLibDosFindNext not necessary: "." and ".." are the first two entries
1678 if ((rc == 0) && isRoot((LPSTR)lpFileName))
1679 {
1680 while ((strcmp(result.achName,".") == 0) || (strcmp(result.achName,"..") == 0))
1681 {
1682 result.achName[0] = 0;
1683 DosError(FERR_DISABLEHARDERR | FERR_DISABLEEXCEPTION);
1684 searchCount = 1;
1685 APIRET rc = DosFindNext(hDir,&result,sizeof(result),&searchCount);
1686 DosError(FERR_ENABLEHARDERR | FERR_ENABLEEXCEPTION);
1687 if (rc)
1688 {
1689 DosFindClose(hDir);
1690 SetLastError(error2WinError(rc));
1691
1692 return INVALID_HANDLE_VALUE_W;
1693 }
1694 }
1695 }
1696 if(rc) {
1697 DosFindClose(hDir);
1698 SetLastError(error2WinError(rc));
1699 return INVALID_HANDLE_VALUE_W;
1700 }
1701 translateFindResults(&result,lpFindFileData);
1702 return hDir;
1703}
1704//******************************************************************************
1705// NOTE: returns "." and ".." in root
1706//******************************************************************************
1707DWORD OSLibDosFindFirstMulti(LPCSTR lpFileName,WIN32_FIND_DATAA *lpFindFileData,DWORD *count)
1708{
1709 HDIR hDir = -1;
1710 ULONG attrs;
1711 FILEFINDBUF3 *result,*data;
1712 ULONG searchCount = *count;
1713
1714 attrs = FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY | FILE_ARCHIVED;
1715 result = (FILEFINDBUF3*)malloc(searchCount*sizeof(FILEFINDBUF3));
1716
1717 DosError(FERR_DISABLEHARDERR | FERR_DISABLEEXCEPTION);
1718 APIRET rc = DosFindFirst((PSZ)lpFileName,&hDir,attrs,result,searchCount*sizeof(FILEFINDBUF3),&searchCount,FIL_STANDARD);
1719 DosError(FERR_ENABLEHARDERR | FERR_ENABLEEXCEPTION);
1720 if (rc)
1721 {
1722 free(result);
1723 *count = 0;
1724 SetLastError(error2WinError(rc));
1725
1726 return INVALID_HANDLE_VALUE_W;
1727 }
1728
1729 data = result;
1730 for (int x = 0;x < searchCount;x++)
1731 {
1732 translateFindResults(data,&lpFindFileData[x]);
1733 data = (FILEFINDBUF3*)(((DWORD)data)+data->oNextEntryOffset);
1734 }
1735 free(result);
1736 *count = searchCount;
1737
1738 return hDir;
1739}
1740//******************************************************************************
1741//******************************************************************************
1742BOOL OSLibDosFindNext(DWORD hFindFile,WIN32_FIND_DATAA *lpFindFileData)
1743{
1744 FILEFINDBUF3 result;
1745 ULONG searchCount = 1;
1746
1747 APIRET rc = DosFindNext((HDIR)hFindFile,&result,sizeof(result),&searchCount);
1748 if (rc)
1749 {
1750 SetLastError(error2WinError(rc));
1751
1752 return FALSE;
1753 }
1754
1755 translateFindResults(&result,lpFindFileData);
1756
1757 return TRUE;
1758}
1759//******************************************************************************
1760//******************************************************************************
1761BOOL OSLibDosFindNextMulti(DWORD hFindFile,WIN32_FIND_DATAA *lpFindFileData,DWORD *count)
1762{
1763 FILEFINDBUF3 *result,*data;
1764 ULONG searchCount = *count;
1765
1766 result = (FILEFINDBUF3*)malloc(searchCount*sizeof(FILEFINDBUF3));
1767 APIRET rc = DosFindNext((HDIR)hFindFile,result,searchCount*sizeof(FILEFINDBUF3),&searchCount);
1768 if (rc)
1769 {
1770 free(result);
1771 *count = 0;
1772 SetLastError(error2WinError(rc));
1773
1774 return FALSE;
1775 }
1776
1777 data = result;
1778 for (int x = 0;x < searchCount;x++)
1779 {
1780 translateFindResults(data,&lpFindFileData[x]);
1781 data = (FILEFINDBUF3*)(((DWORD)data)+data->oNextEntryOffset);
1782 }
1783 free(result);
1784 *count = searchCount;
1785
1786 return TRUE;
1787}
1788//******************************************************************************
1789//******************************************************************************
1790BOOL OSLibDosFindClose(DWORD hFindFile)
1791{
1792 APIRET rc = DosFindClose((HDIR)hFindFile);
1793 if (rc)
1794 {
1795 SetLastError(error2WinError(rc));
1796
1797 return FALSE;
1798 }
1799
1800 return TRUE;
1801}
1802//******************************************************************************
1803#define FSATTACH_SIZE 256
1804//******************************************************************************
1805DWORD OSLibDosQueryVolumeFS(int drive, LPSTR lpFileSystemNameBuffer, DWORD nFileSystemNameSize)
1806{
1807 PFSQBUFFER2 fsinfo = (PFSQBUFFER2) alloca(FSATTACH_SIZE);
1808 ULONG cb = FSATTACH_SIZE;
1809 char drv[3] = "A:";
1810 char *fsname;
1811 APIRET rc;
1812
1813 if(lpFileSystemNameBuffer == NULL) {
1814 DebugInt3();
1815 return ERROR_INVALID_PARAMETER_W;
1816 }
1817 drv[0] = (char)('A' + drive - 1);
1818
1819 DosError(FERR_DISABLEHARDERR);
1820 rc = DosQueryFSAttach(drv, 1, FSAIL_QUERYNAME, fsinfo, &cb);
1821 DosError(FERR_ENABLEHARDERR);
1822
1823 switch(rc) {
1824 case ERROR_INVALID_DRIVE:
1825 return ERROR_INVALID_DRIVE_W;
1826 case ERROR_NO_VOLUME_LABEL:
1827 return ERROR_NO_VOLUME_LABEL_W;
1828 case NO_ERROR:
1829 break;
1830 default:
1831 return ERROR_NOT_ENOUGH_MEMORY; //whatever
1832 }
1833
1834 fsname = (char *)&fsinfo->szName[0] + fsinfo->cbName + 1;
1835 if(strlen(fsname) < nFileSystemNameSize) {
1836 strcpy(lpFileSystemNameBuffer, fsname);
1837 }
1838 else return ERROR_BUFFER_OVERFLOW_W;
1839 return 0;
1840}
1841//******************************************************************************
1842typedef struct _FSINFOBUF
1843{
1844 ULONG ulVolser; /* Volume serial number */
1845 VOLUMELABEL vol; /* Volume lable */
1846} FSINFOBUF;
1847//******************************************************************************
1848DWORD OSLibDosQueryVolumeSerialAndName(int drive, LPDWORD lpVolumeSerialNumber,
1849 LPSTR lpVolumeNameBuffer, DWORD nVolumeNameSize)
1850{
1851 FSINFOBUF fsi;
1852 APIRET rc;
1853
1854 DosError(FERR_DISABLEHARDERR);
1855 rc = DosQueryFSInfo(drive, FSIL_VOLSER, &fsi, sizeof(fsi));
1856 DosError(FERR_ENABLEHARDERR);
1857
1858 switch(rc) {
1859 case ERROR_INVALID_DRIVE:
1860 return ERROR_INVALID_DRIVE_W;
1861 case ERROR_NO_VOLUME_LABEL:
1862 return ERROR_NO_VOLUME_LABEL_W;
1863 case NO_ERROR:
1864 break;
1865 default:
1866 return ERROR_NOT_ENOUGH_MEMORY; //whatever
1867 }
1868
1869 if(lpVolumeSerialNumber) {
1870 *lpVolumeSerialNumber = fsi.ulVolser;
1871 }
1872 if(lpVolumeNameBuffer)
1873 {
1874 if(nVolumeNameSize > fsi.vol.cch) {
1875 strcpy(lpVolumeNameBuffer, (PCHAR)fsi.vol.szVolLabel);
1876 }
1877 else return ERROR_BUFFER_OVERFLOW_W;
1878 }
1879
1880 return ERROR_SUCCESS_W;
1881}
1882//******************************************************************************
1883//******************************************************************************
Note: See TracBrowser for help on using the repository browser.