| /**************************************************************************** |
| * |
| * 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 NT driver |
| * |
| * Description: C library compatible I/O functions for use within a Windows |
| * NT driver. |
| * |
| ****************************************************************************/ |
| |
| #include "pmapi.h" |
| #include "oshdr.h" |
| |
| /*------------------------ Main Code Implementation -----------------------*/ |
| |
| /**************************************************************************** |
| REMARKS: |
| NT driver implementation of the ANSI C fopen function. |
| ****************************************************************************/ |
| FILE * fopen( |
| const char *filename, |
| const char *mode) |
| { |
| ACCESS_MASK DesiredAccess; /* for ZwCreateFile... */ |
| OBJECT_ATTRIBUTES ObjectAttributes; |
| ULONG ShareAccess; |
| ULONG CreateDisposition; |
| NTSTATUS status; |
| HANDLE FileHandle; |
| UNICODE_STRING *uniFile = NULL; |
| PWCHAR bufFile = NULL; |
| IO_STATUS_BLOCK IoStatusBlock; |
| FILE_STANDARD_INFORMATION FileInformation; |
| FILE_POSITION_INFORMATION FilePosition; |
| char kernelFilename[PM_MAX_PATH+5]; |
| FILE *f; |
| |
| /* Add prefix for addressing the file system. "\??\" is short for "\DosDevices\" */ |
| strcpy(kernelFilename, "\\??\\"); |
| strcat(kernelFilename, filename); |
| if ((f = PM_malloc(sizeof(FILE))) == NULL) |
| goto Error; |
| f->offset = 0; |
| f->text = (mode[1] == 't' || mode[2] == 't'); |
| f->writemode = (mode[0] == 'w') || (mode[0] == 'a'); |
| if (mode[0] == 'r') { |
| /* omode = OPEN_ACCESS_READONLY | OPEN_SHARE_COMPATIBLE; */ |
| /* action = ACTION_IFEXISTS_OPEN | ACTION_IFNOTEXISTS_FAIL; */ |
| DesiredAccess = GENERIC_READ; |
| ShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE; |
| CreateDisposition = FILE_OPEN; |
| } |
| else if (mode[0] == 'w') { |
| /* omode = OPEN_ACCESS_WRITEONLY | OPEN_SHARE_COMPATIBLE; */ |
| /* action = ACTION_IFEXISTS_TRUNCATE | ACTION_IFNOTEXISTS_CREATE; */ |
| DesiredAccess = GENERIC_WRITE; |
| ShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE; |
| CreateDisposition = FILE_SUPERSEDE; |
| } |
| else { |
| /* omode = OPEN_ACCESS_READWRITE | OPEN_SHARE_COMPATIBLE; */ |
| /* action = ACTION_IFEXISTS_OPEN | ACTION_IFNOTEXISTS_CREATE; */ |
| DesiredAccess = GENERIC_READ | GENERIC_WRITE; |
| ShareAccess = FILE_SHARE_READ; |
| CreateDisposition = FILE_OPEN_IF; |
| } |
| |
| /* Convert filename string to ansi string and then to UniCode string */ |
| if ((uniFile = _PM_CStringToUnicodeString(kernelFilename)) == NULL) |
| return NULL; |
| |
| /* Create the file */ |
| InitializeObjectAttributes (&ObjectAttributes, |
| uniFile, |
| OBJ_CASE_INSENSITIVE, |
| NULL, |
| NULL); |
| status = ZwCreateFile( &FileHandle, |
| DesiredAccess | SYNCHRONIZE, |
| &ObjectAttributes, |
| &IoStatusBlock, |
| NULL, /* AllocationSize OPTIONAL, */ |
| FILE_ATTRIBUTE_NORMAL, |
| ShareAccess, |
| CreateDisposition, |
| FILE_RANDOM_ACCESS, /* CreateOptions, */ |
| NULL, /* EaBuffer OPTIONAL, */ |
| 0 /* EaLength (required if EaBuffer) */ |
| ); |
| if (!NT_SUCCESS (status)) |
| goto Error; |
| f->handle = (int)FileHandle; |
| |
| /* Determine size of the file */ |
| status = ZwQueryInformationFile( FileHandle, |
| &IoStatusBlock, |
| &FileInformation, |
| sizeof(FILE_STANDARD_INFORMATION), |
| FileStandardInformation |
| ); |
| if (!NT_SUCCESS (status)) |
| goto Error; |
| f->filesize = FileInformation.EndOfFile.LowPart; |
| |
| /* Move to the end of the file if we are appending */ |
| if (mode[0] == 'a') { |
| FilePosition.CurrentByteOffset.HighPart = 0; |
| FilePosition.CurrentByteOffset.LowPart = f->filesize; |
| status = ZwSetInformationFile( FileHandle, |
| &IoStatusBlock, |
| &FilePosition, |
| sizeof(FILE_POSITION_INFORMATION), |
| FilePositionInformation |
| ); |
| if (!NT_SUCCESS (status)) |
| goto Error; |
| } |
| return f; |
| |
| Error: |
| if (f) PM_free(f); |
| if (uniFile) _PM_FreeUnicodeString(uniFile); |
| return NULL; |
| } |
| |
| /**************************************************************************** |
| REMARKS: |
| NT driver implementation of the ANSI C fread function. |
| ****************************************************************************/ |
| size_t fread( |
| void *ptr, |
| size_t size, |
| size_t n, |
| FILE *f) |
| { |
| NTSTATUS status; |
| IO_STATUS_BLOCK IoStatusBlock; |
| LARGE_INTEGER ByteOffset; |
| |
| /* Read any extra bytes from the file */ |
| ByteOffset.HighPart = 0; |
| ByteOffset.LowPart = f->offset; |
| status = ZwReadFile( (HANDLE)f->handle, |
| NULL, /*IN HANDLE Event OPTIONAL, */ |
| NULL, /* IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, */ |
| NULL, /* IN PVOID ApcContext OPTIONAL, */ |
| &IoStatusBlock, |
| ptr, /* OUT PVOID Buffer, */ |
| size * n, /*IN ULONG Length, */ |
| &ByteOffset, /*OPTIONAL, */ |
| NULL /*IN PULONG Key OPTIONAL */ |
| ); |
| if (!NT_SUCCESS (status)) |
| return 0; |
| f->offset += IoStatusBlock.Information; |
| return IoStatusBlock.Information / size; |
| } |
| |
| /**************************************************************************** |
| REMARKS: |
| NT driver implementation of the ANSI C fwrite function. |
| ****************************************************************************/ |
| size_t fwrite( |
| const void *ptr, |
| size_t size, |
| size_t n, |
| FILE *f) |
| { |
| NTSTATUS status; |
| IO_STATUS_BLOCK IoStatusBlock; |
| LARGE_INTEGER ByteOffset; |
| |
| if (!f->writemode) |
| return 0; |
| ByteOffset.HighPart = 0; |
| ByteOffset.LowPart = f->offset; |
| status = ZwWriteFile( (HANDLE)f->handle, |
| NULL, /*IN HANDLE Event OPTIONAL, */ |
| NULL, /* IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, */ |
| NULL, /* IN PVOID ApcContext OPTIONAL, */ |
| &IoStatusBlock, |
| (void*)ptr, /* OUT PVOID Buffer, */ |
| size * n, /*IN ULONG Length, */ |
| &ByteOffset, /*OPTIONAL, */ |
| NULL /*IN PULONG Key OPTIONAL */ |
| ); |
| if (!NT_SUCCESS (status)) |
| return 0; |
| f->offset += IoStatusBlock.Information; |
| if (f->offset > f->filesize) |
| f->filesize = f->offset; |
| return IoStatusBlock.Information / size; |
| } |
| |
| /**************************************************************************** |
| REMARKS: |
| NT driver implementation of the ANSI C fflush function. |
| ****************************************************************************/ |
| int fflush( |
| FILE *f) |
| { |
| /* Nothing to do here as we are not doing buffered I/O */ |
| (void)f; |
| return 0; |
| } |
| |
| /**************************************************************************** |
| REMARKS: |
| NT driver implementation of the ANSI C fseek function. |
| ****************************************************************************/ |
| int fseek( |
| FILE *f, |
| long int offset, |
| int whence) |
| { |
| NTSTATUS status; |
| FILE_POSITION_INFORMATION FilePosition; |
| IO_STATUS_BLOCK IoStatusBlock; |
| |
| if (whence == 0) |
| f->offset = offset; |
| else if (whence == 1) |
| f->offset += offset; |
| else if (whence == 2) |
| f->offset = f->filesize + offset; |
| FilePosition.CurrentByteOffset.HighPart = 0; |
| FilePosition.CurrentByteOffset.LowPart = f->offset; |
| status = ZwSetInformationFile( (HANDLE)f->handle, |
| &IoStatusBlock, |
| &FilePosition, |
| sizeof(FILE_POSITION_INFORMATION), |
| FilePositionInformation |
| ); |
| if (!NT_SUCCESS (status)) |
| return -1; |
| return 0; |
| } |
| |
| /**************************************************************************** |
| REMARKS: |
| NT driver implementation of the ANSI C ftell function. |
| ****************************************************************************/ |
| long ftell( |
| FILE *f) |
| { |
| return f->offset; |
| } |
| |
| /**************************************************************************** |
| REMARKS: |
| NT driver 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: |
| NT driver implementation of the ANSI C fclose function. |
| ****************************************************************************/ |
| int fclose( |
| FILE *f) |
| { |
| ZwClose((HANDLE)f->handle); |
| PM_free(f); |
| return 0; |
| } |