mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
388 lines
9.4 KiB
388 lines
9.4 KiB
/*++
|
|
|
|
Copyright (c) 1991 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
fileio.c
|
|
|
|
Abstract:
|
|
|
|
This source implements a stdio-like facility.
|
|
|
|
Author:
|
|
|
|
Jim Stewart June 1993
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#include "hosts.h"
|
|
#include <string.h>
|
|
|
|
|
|
//
|
|
// Private Definitions
|
|
//
|
|
|
|
|
|
|
|
//
|
|
// Local Variables
|
|
//
|
|
|
|
|
|
|
|
//
|
|
// Local (Private) Functions
|
|
//
|
|
PUCHAR
|
|
LmpMapFile (
|
|
IN HANDLE handle,
|
|
IN OUT int *pnbytes
|
|
);
|
|
|
|
//******************* Pageable Routine Declarations ****************
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma CTEMakePageable(PAGE, LmCloseFile)
|
|
#pragma CTEMakePageable(PAGE, LmFgets)
|
|
#pragma CTEMakePageable(PAGE, LmpMapFile)
|
|
#pragma CTEMakePageable(PAGE, LmOpenFile)
|
|
#endif
|
|
//******************* Pageable Routine Declarations ****************
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
NTSTATUS
|
|
LmCloseFile (
|
|
IN PLM_FILE pfile
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function closes a file opened via LmOpenFile(), and frees its
|
|
LM_FILE object.
|
|
|
|
Arguments:
|
|
|
|
pfile - pointer to the LM_FILE object
|
|
|
|
Return Value:
|
|
|
|
An NTSTATUS value.
|
|
|
|
--*/
|
|
|
|
|
|
{
|
|
NTSTATUS status;
|
|
|
|
CTEPagedCode();
|
|
CTEMemFree(pfile->f_buffer);
|
|
|
|
status = ZwClose(pfile->f_handle);
|
|
|
|
ASSERT(status == STATUS_SUCCESS);
|
|
|
|
CTEMemFree(pfile);
|
|
|
|
return(status);
|
|
|
|
} // LmCloseFile
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
PUCHAR
|
|
LmFgets (
|
|
IN PLM_FILE pfile,
|
|
OUT int *nbytes
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is vaguely similar to fgets(3).
|
|
|
|
Starting at the current seek position, it reads through a newline
|
|
character, or the end of the file. If a newline is encountered, it
|
|
is replaced with a NULL character.
|
|
|
|
Arguments:
|
|
|
|
pfile - file to read from
|
|
nbytes - the number of characters read, excluding the NULL character
|
|
|
|
Return Value:
|
|
|
|
A pointer to the beginning of the line, or NULL if we are at or past
|
|
the end of the file.
|
|
|
|
--*/
|
|
|
|
|
|
{
|
|
PUCHAR endOfLine;
|
|
PUCHAR startOfLine;
|
|
size_t maxBytes;
|
|
|
|
CTEPagedCode();
|
|
startOfLine = pfile->f_current;
|
|
|
|
if (startOfLine >= pfile->f_limit)
|
|
{
|
|
|
|
return((PUCHAR) NULL);
|
|
}
|
|
|
|
maxBytes = (size_t)(pfile->f_limit - pfile->f_current);
|
|
endOfLine = (PUCHAR) memchr(startOfLine, (UCHAR) '\n', maxBytes);
|
|
|
|
if (!endOfLine)
|
|
{
|
|
IF_DBG(NBT_DEBUG_LMHOST)
|
|
KdPrint(("NBT: lmhosts file doesn't end in '\\n'"));
|
|
endOfLine = pfile->f_limit;
|
|
}
|
|
|
|
*endOfLine = (UCHAR) NULL;
|
|
|
|
pfile->f_current = endOfLine + 1;
|
|
(pfile->f_lineno)++;
|
|
ASSERT(pfile->f_current <= pfile->f_limit+1);
|
|
|
|
*nbytes = (int)(endOfLine - startOfLine);
|
|
|
|
return(startOfLine);
|
|
|
|
} // LmFgets
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
PUCHAR
|
|
LmpMapFile (
|
|
IN HANDLE handle,
|
|
IN OUT int *pnbytes
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function reads an entire file into memory.
|
|
|
|
Arguments:
|
|
|
|
handle - file handle
|
|
pnbytes - size of the whole file
|
|
|
|
|
|
Return Value:
|
|
|
|
the buffer allocated, or NULL if unsuccessful.
|
|
|
|
--*/
|
|
|
|
|
|
{
|
|
PUCHAR buffer;
|
|
NTSTATUS status;
|
|
IO_STATUS_BLOCK iostatus;
|
|
FILE_STANDARD_INFORMATION stdInfo;
|
|
LARGE_INTEGER offset ={0, 0};
|
|
LARGE_INTEGER length ={0x7fffffff, 0x7fffffff};
|
|
|
|
CTEPagedCode();
|
|
|
|
|
|
status = ZwQueryInformationFile(
|
|
handle, // FileHandle
|
|
&iostatus, // IoStatusBlock
|
|
(PVOID) &stdInfo, // FileInformation
|
|
sizeof(stdInfo), // Length
|
|
FileStandardInformation); // FileInformationClass
|
|
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
IF_DBG(NBT_DEBUG_LMHOST)
|
|
KdPrint(("NBT: ZwQueryInformationFile(std) = %X\n", status));
|
|
return(NULL);
|
|
}
|
|
|
|
length = stdInfo.EndOfFile; // structure copy
|
|
|
|
if (length.HighPart)
|
|
{
|
|
return(NULL);
|
|
}
|
|
|
|
buffer = NbtAllocMem (length.LowPart+2, NBT_TAG2('18'));
|
|
|
|
if (buffer != NULL)
|
|
{
|
|
|
|
status = ZwReadFile(
|
|
handle, // FileHandle
|
|
NULL, // Event
|
|
NULL, // ApcRoutine
|
|
NULL, // ApcContext
|
|
&iostatus, // IoStatusBlock
|
|
buffer, // Buffer
|
|
length.LowPart, // Length
|
|
&offset, // ByteOffset
|
|
NULL); // Key
|
|
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
IF_DBG(NBT_DEBUG_LMHOST)
|
|
KdPrint(("NBT: ZwReadFile(std) = %X\n", status));
|
|
}
|
|
|
|
ASSERT(status != STATUS_PENDING);
|
|
|
|
if (iostatus.Status != STATUS_SUCCESS || status != STATUS_SUCCESS)
|
|
{
|
|
CTEMemFree(buffer);
|
|
return(NULL);
|
|
}
|
|
|
|
*pnbytes = length.LowPart;
|
|
}
|
|
return(buffer);
|
|
|
|
} // LmpMapFile
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
PLM_FILE
|
|
LmOpenFile (
|
|
IN PUCHAR path
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function opens a file for use by LmFgets().
|
|
|
|
Arguments:
|
|
|
|
path - a fully specified, complete path to the file.
|
|
|
|
Return Value:
|
|
|
|
A pointer to an LM_FILE object, or NULL if unsuccessful.
|
|
|
|
--*/
|
|
|
|
|
|
{
|
|
NTSTATUS status;
|
|
HANDLE handle;
|
|
PLM_FILE pfile;
|
|
IO_STATUS_BLOCK iostatus;
|
|
OBJECT_ATTRIBUTES attributes;
|
|
UNICODE_STRING ucPath;
|
|
PUCHAR start;
|
|
int nbytes;
|
|
OEM_STRING String;
|
|
PUCHAR LongerPath;
|
|
|
|
|
|
CTEPagedCode();
|
|
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
|
|
|
|
status = LmGetFullPath(path,&LongerPath);
|
|
|
|
if (NT_SUCCESS(status))
|
|
{
|
|
RtlInitString(&String,LongerPath);
|
|
|
|
status = RtlAnsiStringToUnicodeString(&ucPath,&String,TRUE);
|
|
|
|
if (NT_SUCCESS(status))
|
|
{
|
|
|
|
#ifdef HDL_FIX
|
|
InitializeObjectAttributes (&attributes, // POBJECT_ATTRIBUTES
|
|
&ucPath, // ObjectName
|
|
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, // Attributes
|
|
(HANDLE) NULL, // RootDirectory
|
|
(PSECURITY_DESCRIPTOR) NULL); // SecurityDescriptor
|
|
#else
|
|
InitializeObjectAttributes (&attributes, // POBJECT_ATTRIBUTES
|
|
&ucPath, // ObjectName
|
|
OBJ_CASE_INSENSITIVE, // Attributes
|
|
(HANDLE) NULL, // RootDirectory
|
|
(PSECURITY_DESCRIPTOR) NULL); // SecurityDescriptor
|
|
#endif // HDL_FIX
|
|
|
|
status = ZwCreateFile (&handle, // FileHandle
|
|
SYNCHRONIZE | FILE_READ_DATA, // DesiredAccess
|
|
&attributes, // ObjectAttributes
|
|
&iostatus, // IoStatusBlock
|
|
0, // AllocationSize
|
|
FILE_ATTRIBUTE_NORMAL, // FileAttributes
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE, // ShareAccess
|
|
FILE_OPEN, // CreateDisposition
|
|
FILE_SYNCHRONOUS_IO_NONALERT, // OpenOptions
|
|
NULL, // EaBuffer
|
|
0); // EaLength
|
|
|
|
if (NT_SUCCESS(status))
|
|
{
|
|
start = LmpMapFile(handle, &nbytes);
|
|
|
|
if (start)
|
|
{
|
|
pfile = (PLM_FILE) NbtAllocMem (sizeof(LM_FILE), NBT_TAG2('19'));
|
|
if (pfile)
|
|
{
|
|
KeInitializeSpinLock(&(pfile->f_lock));
|
|
|
|
pfile->f_refcount = 1;
|
|
pfile->f_handle = handle;
|
|
pfile->f_lineno = 0;
|
|
pfile->f_fileOffset.HighPart = 0;
|
|
pfile->f_fileOffset.LowPart = 0;
|
|
|
|
pfile->f_current = start;
|
|
pfile->f_buffer = start;
|
|
pfile->f_limit = pfile->f_buffer + nbytes;
|
|
|
|
RtlFreeUnicodeString(&ucPath);
|
|
CTEMemFree(LongerPath);
|
|
|
|
return(pfile);
|
|
}
|
|
|
|
CTEMemFree(start);
|
|
}
|
|
|
|
ZwClose(handle);
|
|
}
|
|
|
|
RtlFreeUnicodeString(&ucPath);
|
|
|
|
IF_DBG(NBT_DEBUG_LMHOST)
|
|
KdPrint(("Nbt.LmOpenFile: ZwOpenFile(std) = %X\n", status));
|
|
|
|
}
|
|
|
|
CTEMemFree(LongerPath);
|
|
}
|
|
|
|
return((PLM_FILE) NULL);
|
|
|
|
} // LmOpenFile
|
|
|