/**************************************************************************** * * 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; }