| /**************************************************************************** |
| * |
| * SciTech OS Portability Manager Library |
| * |
| * ======================================================================== |
| * |
| * The contents of this file are subject to the SciTech MGL Public |
| * License Version 1.0 (the "License"); you may not use this file |
| * except in compliance with the License. You may obtain a copy of |
| * the License at http://www.scitechsoft.com/mgl-license.txt |
| * |
| * Software distributed under the License is distributed on an |
| * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or |
| * implied. See the License for the specific language governing |
| * rights and limitations under the License. |
| * |
| * The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc. |
| * |
| * The Initial Developer of the Original Code is SciTech Software, Inc. |
| * All Rights Reserved. |
| * |
| * ======================================================================== |
| * |
| * Language: ANSI C |
| * Environment: 32-bit Windows VxD |
| * |
| * Description: C library compatible I/O functions for use within a VxD. |
| * |
| ****************************************************************************/ |
| |
| #include "pmapi.h" |
| #include "vxdfile.h" |
| |
| /*------------------------ Main Code Implementation -----------------------*/ |
| |
| #define EOF -1 |
| |
| /**************************************************************************** |
| REMARKS: |
| VxD implementation of the ANSI C fopen function. |
| ****************************************************************************/ |
| FILE * fopen( |
| const char *filename, |
| const char *mode) |
| { |
| FILE *f = PM_malloc(sizeof(FILE)); |
| long oldpos; |
| |
| if (f) { |
| f->offset = 0; |
| f->text = (mode[1] == 't' || mode[2] == 't'); |
| f->writemode = (mode[0] == 'w') || (mode[0] == 'a'); |
| if (initComplete) { |
| WORD omode,error; |
| BYTE action; |
| |
| if (mode[0] == 'r') { |
| omode = OPEN_ACCESS_READONLY | OPEN_SHARE_COMPATIBLE; |
| action = ACTION_IFEXISTS_OPEN | ACTION_IFNOTEXISTS_FAIL; |
| } |
| else if (mode[0] == 'w') { |
| omode = OPEN_ACCESS_WRITEONLY | OPEN_SHARE_COMPATIBLE; |
| action = ACTION_IFEXISTS_TRUNCATE | ACTION_IFNOTEXISTS_CREATE; |
| } |
| else { |
| omode = OPEN_ACCESS_READWRITE | OPEN_SHARE_COMPATIBLE; |
| action = ACTION_IFEXISTS_OPEN | ACTION_IFNOTEXISTS_CREATE; |
| } |
| f->handle = (int)R0_OpenCreateFile(false,(char*)filename,omode,ATTR_NORMAL,action,0,&error,&action); |
| if (f->handle == 0) { |
| PM_free(f); |
| return NULL; |
| } |
| f->filesize = R0_GetFileSize((HANDLE)f->handle,&error); |
| if (mode[0] == 'a') |
| fseek(f,0,2); |
| } |
| else { |
| int oflag,pmode; |
| |
| if (mode[0] == 'r') { |
| pmode = _S_IREAD; |
| oflag = _O_RDONLY; |
| } |
| else if (mode[0] == 'w') { |
| pmode = _S_IWRITE; |
| oflag = _O_WRONLY | _O_CREAT | _O_TRUNC; |
| } |
| else { |
| pmode = _S_IWRITE; |
| oflag = _O_RDWR | _O_CREAT | _O_APPEND; |
| } |
| if (f->text) |
| oflag |= _O_TEXT; |
| else |
| oflag |= _O_BINARY; |
| if ((f->handle = i_open(filename,oflag,pmode)) == -1) { |
| PM_free(f); |
| return NULL; |
| } |
| oldpos = i_lseek(f->handle,0,1); |
| f->filesize = i_lseek(f->handle,0,2); |
| i_lseek(f->handle,oldpos,0); |
| } |
| } |
| return f; |
| } |
| |
| /**************************************************************************** |
| REMARKS: |
| VxD implementation of the ANSI C fread function. Note that the VxD file I/O |
| functions are layered on DOS, so can only read up to 64K at a time. Since |
| we are expected to handle much larger chunks than this, we handle larger |
| blocks automatically in here. |
| ****************************************************************************/ |
| size_t fread( |
| void *ptr, |
| size_t size, |
| size_t n, |
| FILE *f) |
| { |
| char *buf = ptr; |
| WORD error; |
| int bytes = size * n; |
| int readbytes,totalbytes = 0; |
| |
| while (bytes > 0x10000) { |
| if (initComplete) { |
| readbytes = R0_ReadFile(false,(HANDLE)f->handle,buf,0x8000,f->offset,&error); |
| readbytes += R0_ReadFile(false,(HANDLE)f->handle,buf+0x8000,0x8000,f->offset+0x8000,&error); |
| } |
| else { |
| readbytes = i_read(f->handle,buf,0x8000); |
| readbytes += i_read(f->handle,buf+0x8000,0x8000); |
| } |
| totalbytes += readbytes; |
| f->offset += readbytes; |
| buf += 0x10000; |
| bytes -= 0x10000; |
| } |
| if (bytes) { |
| if (initComplete) |
| readbytes = R0_ReadFile(false,(HANDLE)f->handle,buf,bytes,f->offset,&error); |
| else |
| readbytes = i_read(f->handle,buf,bytes); |
| totalbytes += readbytes; |
| f->offset += readbytes; |
| } |
| return totalbytes / size; |
| } |
| |
| /**************************************************************************** |
| REMARKS: |
| VxD implementation of the ANSI C fwrite function. Note that the VxD file I/O |
| functions are layered on DOS, so can only read up to 64K at a time. Since |
| we are expected to handle much larger chunks than this, we handle larger |
| blocks automatically in here. |
| ****************************************************************************/ |
| size_t fwrite( |
| const void *ptr, |
| size_t size, |
| size_t n, |
| FILE *f) |
| { |
| const char *buf = ptr; |
| WORD error; |
| int bytes = size * n; |
| int writtenbytes,totalbytes = 0; |
| |
| if (!f->writemode) |
| return 0; |
| while (bytes > 0x10000) { |
| if (initComplete) { |
| writtenbytes = R0_WriteFile(false,(HANDLE)f->handle,buf,0x8000,f->offset,&error); |
| writtenbytes += R0_WriteFile(false,(HANDLE)f->handle,buf+0x8000,0x8000,f->offset+0x8000,&error); |
| } |
| else { |
| writtenbytes = i_write(f->handle,buf,0x8000); |
| writtenbytes += i_write(f->handle,buf+0x8000,0x8000); |
| } |
| totalbytes += writtenbytes; |
| f->offset += writtenbytes; |
| buf += 0x10000; |
| bytes -= 0x10000; |
| } |
| if (initComplete) |
| writtenbytes = R0_WriteFile(false,(HANDLE)f->handle,buf,bytes,f->offset,&error); |
| else |
| writtenbytes = i_write(f->handle,buf,bytes); |
| totalbytes += writtenbytes; |
| f->offset += writtenbytes; |
| if (f->offset > f->filesize) |
| f->filesize = f->offset; |
| return totalbytes / size; |
| } |
| |
| /**************************************************************************** |
| REMARKS: |
| VxD implementation of the ANSI C fflush function. |
| ****************************************************************************/ |
| int fflush( |
| FILE *f) |
| { |
| // Nothing to do since we are not doing buffered file I/O |
| (void)f; |
| return 0; |
| } |
| |
| /**************************************************************************** |
| REMARKS: |
| VxD implementation of the ANSI C fseek function. |
| ****************************************************************************/ |
| int fseek( |
| FILE *f, |
| long int offset, |
| int whence) |
| { |
| if (whence == 0) |
| f->offset = offset; |
| else if (whence == 1) |
| f->offset += offset; |
| else if (whence == 2) |
| f->offset = f->filesize + offset; |
| if (!initComplete) |
| i_lseek(f->handle,f->offset,0); |
| return 0; |
| } |
| |
| /**************************************************************************** |
| REMARKS: |
| VxD implementation of the ANSI C ftell function. |
| ****************************************************************************/ |
| long ftell( |
| FILE *f) |
| { |
| return f->offset; |
| } |
| |
| /**************************************************************************** |
| REMARKS: |
| VxD implementation of the ANSI C feof function. |
| ****************************************************************************/ |
| int feof( |
| FILE *f) |
| { |
| return (f->offset == f->filesize); |
| } |
| |
| /**************************************************************************** |
| REMARKS: |
| NT driver implementation of the ANSI C fgets function. |
| ****************************************************************************/ |
| char *fgets( |
| char *s, |
| int n, |
| FILE *f) |
| { |
| int len; |
| char *cs; |
| |
| // Read the entire buffer into memory (our functions are unbuffered!) |
| if ((len = fread(s,1,n,f)) == 0) |
| return NULL; |
| |
| // Search for '\n' or end of string |
| if (n > len) |
| n = len; |
| cs = s; |
| while (--n > 0) { |
| if (*cs == '\n') |
| break; |
| cs++; |
| } |
| *cs = '\0'; |
| return s; |
| } |
| |
| /**************************************************************************** |
| REMARKS: |
| NT driver implementation of the ANSI C fputs function. |
| ****************************************************************************/ |
| int fputs( |
| const char *s, |
| FILE *f) |
| { |
| return fwrite(s,1,strlen(s),f); |
| } |
| |
| /**************************************************************************** |
| REMARKS: |
| VxD implementation of the ANSI C fclose function. |
| ****************************************************************************/ |
| int fclose( |
| FILE *f) |
| { |
| WORD error; |
| |
| if (initComplete) |
| R0_CloseFile((HANDLE)f->handle,&error); |
| else |
| i_close(f->handle); |
| PM_free(f); |
| return 0; |
| } |
| |