389 lines
9.4 KiB
C
389 lines
9.4 KiB
C
|
/*++
|
|||
|
|
|||
|
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
|
|||
|
|