331 lines
10 KiB
C
331 lines
10 KiB
C
/****************************************************************************
|
|
*
|
|
* 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;
|
|
}
|