summaryrefslogblamecommitdiffstats
path: root/private/ntos/nbt/nt/fileio.c
blob: 5490c3acd3acabffb7698dc5973e40ef024af781 (plain) (tree)































































































































































































































































































































































































                                                                                     
/*++

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 "nbtprocs.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  = 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 = 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 = ExAllocatePool(NonPagedPool, length.LowPart+2);

    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))
        {

            InitializeObjectAttributes(
                        &attributes,                        // POBJECT_ATTRIBUTES
                        &ucPath,                            // ObjectName
                        OBJ_CASE_INSENSITIVE,               // Attributes
                        (HANDLE) NULL,                      // RootDirectory
                        (PSECURITY_DESCRIPTOR) NULL);       // SecurityDescriptor

            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) ExAllocatePool(NonPagedPool, sizeof(LM_FILE));

                    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: ZwOpenFile(std) = %X\n", status));

        }

        CTEMemFree(LongerPath);
    }

    return((PLM_FILE) NULL);

} // LmOpenFile