//+----------------------------------------------------------------------------
//
//  Copyright (C) 1992, Microsoft Corporation.
//
//  File:       UPkt.c
//
//  Contents:   This module contains user mode functions which support
//              operations on the DFS Partition Knowledge Table.
//
//  Functions:  PktOpen -
//              PktClose -
//              PktCreateEntry -
//              PktCreateSubordinateEntry -
//              PktFlushCache -
//              PktDestroyEntry -
//              PktModifyEntryGuid -
//              PktSetRelationInfo -
//
//  History:
//
//  [mikese] I replaced MemAlloc's by malloc's, but consider using
//                   RtlAllocateHeap.
//          Also, most of the routines in the module have a remarkably similar
//          structure, and could probably be recoded using a common subroutine.
//
//-----------------------------------------------------------------------------


#include <ntifs.h>
#include <ntext.h>
#include "dfsmrshl.h"
#include "nodetype.h"
#include "libsup.h"
#include "upkt.h"
#include "dfsfsctl.h"
#include "fsctrl.h"    // needed for FSCTL_DFS_PKT_FLUSH_CACHE

#define MAX_OUT_BUFFER_SIZE_RELINFO     0x1000  


//+-------------------------------------------------------------------------
//
//  Function:   PktOpen, public
//
//  Synopsis:   Returns a handle to the Dfs PKT so operations can be made
//              to it.
//
//  Arguments:
//
//  Returns:    [STATUS_SUCCESS] -- Successfully opened the pkt.
//
//              [STATUS_FS_DRIVER_REQUIRED] -- Dfs driver not loaded
//
//--------------------------------------------------------------------------

NTSTATUS
PktOpen(
    IN  OUT PHANDLE PktHandle,
    IN      ACCESS_MASK DesiredAccess,
    IN      ULONG ShareAccess,
    IN      PUNICODE_STRING DfsNtPathName OPTIONAL
)
{
    NTSTATUS status;
    HANDLE dfsHandle;

    status = DfsOpen(&dfsHandle, DfsNtPathName);

    if(NT_SUCCESS(status)) {

       *PktHandle = dfsHandle;

    } else {

        status = STATUS_FS_DRIVER_REQUIRED;

    }

    return status;
}


//+-------------------------------------------------------------------------
//
//  Function:   PktClose, public
//
//  Synopsis:
//
//  Arguments:
//
//  Returns:    Nothing
//
//--------------------------------------------------------------------------
VOID
PktClose(
    IN      HANDLE PktHandle
)
{
    NTSTATUS status = STATUS_SUCCESS;

    if(NT_SUCCESS(status))
        NtClose(PktHandle);
}


//+-------------------------------------------------------------------------
//
//  Function:   PktCreateEntry, public
//
//  Synopsis:
//
//  Arguments:
//
//  Returns:
//
//--------------------------------------------------------------------------

NTSTATUS
PktCreateEntry(
    IN      HANDLE PktHandle,
    IN      ULONG EntryType,
    IN      PDFS_PKT_ENTRY_ID EntryId,
    IN      PDFS_PKT_ENTRY_INFO EntryInfo,
    IN      ULONG CreateDisposition
)
{
    NTSTATUS                    status;
    DFS_PKT_CREATE_ENTRY_ARG    arg;
    MARSHAL_BUFFER              marshalBuffer;
    ULONG                       size;

    arg.EntryType = EntryType;
    arg.EntryId = (*EntryId);
    arg.EntryInfo = (*EntryInfo);
    arg.CreateDisposition = CreateDisposition;

    size = 0L;
    status = DfsRtlSize(&MiPktCreateEntryArg, &arg, &size);
    if(NT_SUCCESS(status))
    {

        PVOID buffer = malloc ( size );

        if ( buffer == NULL )
            return(STATUS_NO_MEMORY);

        MarshalBufferInitialize(&marshalBuffer, size, buffer);
        status = DfsRtlPut(
            &marshalBuffer,
            &MiPktCreateEntryArg,
            &arg
        );

        if(NT_SUCCESS(status))
        {

            status = DfsFsctl(
                PktHandle,
                FSCTL_DFS_PKT_CREATE_ENTRY,
                buffer,
                size,
                NULL,
                0L
            );
        }
        free(buffer);
    }
    return status;
}


//+-------------------------------------------------------------------------
//
//  Function:   PktCreateSubordinateEntry, public
//
//  Synopsis:
//
//  Arguments:
//
//  Returns:
//
//--------------------------------------------------------------------------

NTSTATUS
PktCreateSubordinateEntry(
    IN      HANDLE PktHandle,
    IN      PDFS_PKT_ENTRY_ID SuperiorId,
    IN      ULONG SubordinateType,
    IN      PDFS_PKT_ENTRY_ID SubordinateId,
    IN      PDFS_PKT_ENTRY_INFO SubordinateInfo OPTIONAL,
    IN      ULONG CreateDisposition
)
{
    NTSTATUS                                    status;
    DFS_PKT_CREATE_SUBORDINATE_ENTRY_ARG        arg;
    MARSHAL_BUFFER                              marshalBuffer;
    ULONG                                       size;

    arg.EntryId = (*SuperiorId);
    arg.SubEntryType = SubordinateType;
    arg.SubEntryId = (*SubordinateId);
    arg.SubEntryInfo = (*SubordinateInfo);
    arg.CreateDisposition = CreateDisposition;

    size = 0L;
    status = DfsRtlSize(&MiPktCreateSubordinateEntryArg, &arg, &size);
    if(NT_SUCCESS(status)) {

        PVOID buffer = malloc ( size );

        if ( buffer == NULL )
            return(STATUS_NO_MEMORY);

        MarshalBufferInitialize(&marshalBuffer, size, buffer);
        status = DfsRtlPut(
            &marshalBuffer,
            &MiPktCreateSubordinateEntryArg,
            &arg
        );

        if(NT_SUCCESS(status)) {

            status = DfsFsctl(
                PktHandle,
                FSCTL_DFS_PKT_CREATE_SUBORDINATE_ENTRY,
                buffer,
                size,
                NULL,
                0L
            );
        }
        free(buffer);
    }
    return status;
}



//+-------------------------------------------------------------------------
//
//  Function:   PktDestroyEntry, public
//
//  Synopsis:
//
//  Arguments:
//
//  Returns:
//
//--------------------------------------------------------------------------

NTSTATUS
PktDestroyEntry(
    IN      HANDLE PktHandle,
    IN      DFS_PKT_ENTRY_ID    victim
)
{
    NTSTATUS            status;
    MARSHAL_BUFFER      marshalBuffer;
    ULONG               size;

    size = 0L;
    status = DfsRtlSize(&MiPktEntryId, &victim, &size);
    if(NT_SUCCESS(status))
    {
        PVOID buffer = malloc ( size );

        if ( buffer == NULL )
            return(STATUS_NO_MEMORY);

        MarshalBufferInitialize(&marshalBuffer, size, buffer);
        status = DfsRtlPut(
            &marshalBuffer,
            &MiPktEntryId,
            &victim
        );

        if(NT_SUCCESS(status))
        {

            status = DfsFsctl(
                PktHandle,
                FSCTL_DFS_PKT_DESTROY_ENTRY,
                buffer,
                size,
                NULL,
                0L
            );
        }
        free(buffer);
    }
    return status;
}


//+-------------------------------------------------------------------------
//
//  Function:   PktGetRelationInfo, public
//
//  Synopsis:
//
//  Arguments:
//
//  Returns:
//
//  Notes:      The relationalInfo structure should be made available
//              by the caller but additional memory is allocated in here.
//              The caller should deallocate all that memory himself.
//
//--------------------------------------------------------------------------
NTSTATUS
PktGetRelationInfo(
    IN      HANDLE PktHandle,
    IN      PDFS_PKT_ENTRY_ID   EntryId,
    IN OUT  PDFS_PKT_RELATION_INFO RelationInfo
)
{
    NTSTATUS            status;
    MARSHAL_BUFFER      marshalBuffer;
    ULONG               size;
    PVOID               OutputBuffer;

    size = 0L;
    status = DfsRtlSize(&MiPktEntryId, EntryId, &size);
    if(NT_SUCCESS(status))
    {
        PVOID buffer = malloc ( size );

        if ( buffer == NULL )
            return(STATUS_NO_MEMORY);

        MarshalBufferInitialize(&marshalBuffer, size, buffer);
        status = DfsRtlPut(
            &marshalBuffer,
            &MiPktEntryId,
            EntryId
        );


        if(NT_SUCCESS(status))
        {

            // Do we want to retry with larger sizes?
            OutputBuffer = malloc ( MAX_OUT_BUFFER_SIZE_RELINFO );
            if ( OutputBuffer == NULL )
            {
                status = STATUS_INSUFFICIENT_RESOURCES;
            }
            else
            {

                status = DfsFsctl(
                            PktHandle,
                            FSCTL_DFS_PKT_GET_RELATION_INFO,
                            buffer,
                            size,
                            OutputBuffer,
                            MAX_OUT_BUFFER_SIZE_RELINFO);

                //
                // We can get rid of this right away.
                //


                if(NT_SUCCESS(status)) {

                    MarshalBufferInitialize(
                        &marshalBuffer,
                        MAX_OUT_BUFFER_SIZE_RELINFO,
                        OutputBuffer
                    );

                    status = DfsRtlGet(
                        &marshalBuffer,
                        &MiPktRelationInfo,
                        RelationInfo
                    );
                }

                free(OutputBuffer);
            }
        }
        free(buffer);

    }   //Status from DfsRtlSize

    if (!NT_SUCCESS(status))    {
        RtlZeroMemory(RelationInfo, sizeof(DFS_PKT_RELATION_INFO));
    }

    return status;
}


//+----------------------------------------------------------------------------
//
//  Function:   PktValidateLocalVolumeInfo, public
//
//  Synopsis:   Asks the Dfs driver to validate its local volume info with
//              the one that is passed in.
//
//  Arguments:  [relationInfo] -- The DFS_PKT_RELATION_INFO to validate
//                      against.
//
//  Returns:    [STATUS_SUCCESS] -- Successfully validated local volume info
//
//              [STATUS_REGISTRY_RECOVERED] -- Successfully validated info,
//                      but had to make changes to local info
//
//              [DFS_STATUS_NOSUCH_LOCAL_VOLUME] -- The driver has no record
//                      of local volume described in relation info.
//
//              [STATUS_UNSUCCESSFUL] -- Unable to fixup the local relation
//                      info. An appropriate message was logged to the
//                      local eventlog.
//
//              [STATUS_DATA_ERROR] -- Passed in relationInfo is bogus.
//
//              [STATUS_INSUFFICIENT_RESOURCES] -- Out of memory condition.
//
//              [STATUS_FS_DRIVER_REQUIRED] -- Unable to open handle to the
//                      Dfs driver
//
//-----------------------------------------------------------------------------

NTSTATUS
PktValidateLocalVolumeInfo(
    IN PDFS_PKT_RELATION_INFO relationInfo)
{
    NTSTATUS status;
    HANDLE dfsHandle;
    MARSHAL_BUFFER marshalBuffer;
    PUCHAR pBuffer;
    ULONG cbBuffer;

    status = DfsOpen(&dfsHandle, NULL);

    if (NT_SUCCESS(status)) {

        cbBuffer = 0;

        status = DfsRtlSize( &MiPktRelationInfo, relationInfo, &cbBuffer );

        if (NT_SUCCESS(status)) {

            pBuffer = malloc( cbBuffer );

            if (pBuffer != NULL) {

                MarshalBufferInitialize(&marshalBuffer, cbBuffer, pBuffer);

                status = DfsRtlPut(
                            &marshalBuffer,
                            &MiPktRelationInfo,
                            relationInfo);


            } else {

                status = STATUS_INSUFFICIENT_RESOURCES;

            }

            if (NT_SUCCESS(status)) {

                status = DfsFsctl(
                            dfsHandle,
                            FSCTL_DFS_VERIFY_LOCAL_VOLUME_KNOWLEDGE,
                            pBuffer,
                            cbBuffer,
                            NULL,
                            0);

            }

            if (pBuffer != NULL)
                free(pBuffer);

        }

        NtClose( dfsHandle );

    }

    return( status );

}


//+----------------------------------------------------------------------------
//
//  Function:   PktPruneLocalPartition
//
//  Synopsis:   Asks the Dfs Driver to get rid of a local volume that is
//              not supposed to be supported by this server.
//
//  Arguments:  [EntryId] -- The entry id of the volume to prune.
//
//  Returns:    [STATUS_SUCCESS] -- Successfully pruned the volume
//
//              [DFS_STATUS_NOSUCH_LOCAL_VOLUME] -- The driver has no record
//                      of local volume described in relation info.
//
//              [STATUS_UNSUCCESSFUL] -- Unable to fixup the local relation
//                      info. An appropriate message was logged to the
//                      local eventlog.
//
//              [STATUS_DATA_ERROR] -- Passed in relationInfo is bogus.
//
//              [STATUS_INSUFFICIENT_RESOURCES] -- Out of memory condition.
//
//              [STATUS_FS_DRIVER_REQUIRED] -- Unable to open handle to the
//                      Dfs driver
//
//-----------------------------------------------------------------------------

NTSTATUS
PktPruneLocalPartition(
    IN PDFS_PKT_ENTRY_ID EntryId)
{
    NTSTATUS status;
    HANDLE dfsHandle;
    MARSHAL_BUFFER marshalBuffer;
    PUCHAR pBuffer;
    ULONG cbBuffer;

    status = DfsOpen(&dfsHandle, NULL);

    if (NT_SUCCESS(status)) {

        cbBuffer = 0;

        status = DfsRtlSize( &MiPktEntryId, EntryId, &cbBuffer );

        if (NT_SUCCESS(status)) {

            pBuffer = malloc( cbBuffer );

            if (pBuffer != NULL) {

                MarshalBufferInitialize(&marshalBuffer, cbBuffer, pBuffer);

                status = DfsRtlPut(
                            &marshalBuffer,
                            &MiPktEntryId,
                            EntryId);


            } else {

                status = STATUS_INSUFFICIENT_RESOURCES;

            }

            if (NT_SUCCESS(status)) {

                status = DfsFsctl(
                            dfsHandle,
                            FSCTL_DFS_PRUNE_LOCAL_PARTITION,
                            pBuffer,
                            cbBuffer,
                            NULL,
                            0);

            }

            if (pBuffer != NULL)
                free(pBuffer);

        }

        NtClose( dfsHandle );

    }

    return( status );
}


//+----------------------------------------------------------------------------
//
//  Function:   PktIsChildnameLegal, public
//
//  Synopsis:
//
//  Arguments:
//
//  Returns:
//
//-----------------------------------------------------------------------------

NTSTATUS
PktIsChildnameLegal(
    IN PWCHAR   pwszParent,
    IN PWCHAR   pwszChild,
    IN GUID     *pidChild)
{
    HANDLE           dfsHandle;
    NTSTATUS         Status;
    DFS_PKT_ENTRY_ID idParent, idChild;
    MARSHAL_BUFFER   marshalBuffer;
    PUCHAR           pBuffer;
    ULONG            cbBuffer;

    RtlZeroMemory( &idParent, sizeof(DFS_PKT_ENTRY_ID) );

    RtlZeroMemory( &idChild, sizeof(DFS_PKT_ENTRY_ID) );

    RtlInitUnicodeString( &idParent.Prefix, pwszParent );

    RtlInitUnicodeString( &idChild.Prefix, pwszChild );

    idChild.Uid = *pidChild;

    cbBuffer = 0;

    Status = DfsOpen(&dfsHandle, NULL);

    if (NT_SUCCESS(Status)) {

        Status = DfsRtlSize( &MiPktEntryId, &idParent, &cbBuffer );

        if (NT_SUCCESS(Status)) {

            Status = DfsRtlSize( &MiPktEntryId, &idChild, &cbBuffer );
        }

        if (NT_SUCCESS(Status)) {

            pBuffer = malloc( cbBuffer );

            if (pBuffer != NULL) {

                MarshalBufferInitialize( &marshalBuffer, cbBuffer, pBuffer );

                Status = DfsRtlPut(
                            &marshalBuffer,
                            &MiPktEntryId,
                            &idParent );

                if (NT_SUCCESS(Status)) {

                    Status = DfsRtlPut(
                                &marshalBuffer,
                                &MiPktEntryId,
                                &idChild );

                }

                if (NT_SUCCESS(Status)) {

                    Status = DfsFsctl(
                                dfsHandle,
                                FSCTL_DFS_IS_CHILDNAME_LEGAL,
                                pBuffer,
                                cbBuffer,
                                NULL,
                                0L);

                }

                free( pBuffer );

            } else {

                Status = STATUS_INSUFFICIENT_RESOURCES;

            }

        }

        NtClose( dfsHandle );

    }

    return( Status );

}


//+----------------------------------------------------------------------------
//
//  Function:   PktGetEntryType, public
//
//  Synopsis:   Given a prefix, this routine retrieves the entry type of the
//              PktEntry
//
//  Arguments:  [pwszPrefix] -- The prefix whose PktEntry's type is required
//              [pType] -- The type is returned here.
//
//  Returns:
//
//-----------------------------------------------------------------------------

NTSTATUS
PktGetEntryType(
    IN PWSTR pwszPrefix,
    IN PULONG pType)
{
    HANDLE           dfsHandle;
    NTSTATUS         Status;

    Status = DfsOpen(&dfsHandle, NULL);

    if (NT_SUCCESS(Status)) {

        Status = DfsFsctl(
                    dfsHandle,
                    FSCTL_DFS_GET_ENTRY_TYPE,
                    pwszPrefix,
                    wcslen(pwszPrefix) * sizeof(WCHAR),
                    pType,
                    sizeof(ULONG));

        NtClose( dfsHandle );

    }

    return( Status );

}

//+----------------------------------------------------------------------------
//
//  Function:   DfsSetServiceState
//
//  Synopsis:   Sets the state of a service on a volume.
//
//  Arguments:  [VolumeId] -- The volume on which to operate
//              [ServiceName] -- Name of service
//              [State] -- Either 0 or DFS_SERVICE_TYPE_OFFLINE
//
//  Returns:    [STATUS_SUCCESS] -- The specified replica was set
//                      online/offline as speficied.
//
//              [DFS_STATUS_NO_SUCH_ENTRY] -- The specified volume was not
//                      found, or the specified replica is not a server for
//                      the volume.
//
//              [STATUS_DATA_ERROR] -- marshalling or unmarshalling error.
//
//              [STATUS_INSUFFICIENT_RESOURCES] -- Out of memory situation.
//
//              Status from opening handle to the Dfs driver.
//
//-----------------------------------------------------------------------------

NTSTATUS
DfsSetServiceState(
    IN PDFS_PKT_ENTRY_ID VolumeId,
    IN PWSTR ServiceName,
    IN ULONG State)
{
    NTSTATUS                    status;
    HANDLE                      dfsHandle = NULL;
    DFS_DC_SET_SERVICE_STATE    setSvcState;
    MARSHAL_BUFFER              marshalBuffer;
    PUCHAR                       buffer = NULL;
    ULONG                       size;

    status = DfsOpen( &dfsHandle, NULL );

    if (NT_SUCCESS(status)) {

        setSvcState.Id = *VolumeId;
        RtlInitUnicodeString(
            &setSvcState.ServiceName,
            ServiceName);
        setSvcState.State = State;

        size = 0;

        status = DfsRtlSize( &MiDCSetServiceState, &setSvcState, &size );

        if (NT_SUCCESS(status)) {

            buffer = (PUCHAR) malloc( size );

            if (buffer == NULL) {

                status = STATUS_INSUFFICIENT_RESOURCES;

            }

        }

        if (NT_SUCCESS(status)) {

            MarshalBufferInitialize( &marshalBuffer, size, buffer );

            status = DfsRtlPut( &
                        marshalBuffer,
                        &MiDCSetServiceState,
                        &setSvcState );

        }

        if (NT_SUCCESS(status)) {

            status = DfsFsctl(
                        dfsHandle,
                        FSCTL_DFS_SET_SERVICE_STATE,
                        buffer,
                        size,
                        NULL,
                        0);

        }

        NtClose( dfsHandle );

        if (buffer != NULL) {

            free( buffer );

        }

    }

    return( status );

}

//+----------------------------------------------------------------------------
//
//  Function:   DfsDCSetVolumeState
//
//  Synopsis:   Sets the state of a volume in the DCs. This will control
//              whether referrals will be given out to this volume or not.
//
//  Arguments:  [VolumeId] -- The volume on which to operate
//              [State] -- Either 0 or PKT_ENTRY_TYPE_OFFLINE
//
//  Returns:    [STATUS_SUCCESS] -- The specified replica was set
//                      online/offline as speficied.
//
//              [DFS_STATUS_NO_SUCH_ENTRY] -- The specified volume was not
//                      found.
//
//              [STATUS_DATA_ERROR] -- marshalling or unmarshalling error.
//
//              [STATUS_INSUFFICIENT_RESOURCES] -- Out of memory situation.
//
//              Status from opening handle to the Dfs driver.
//
//-----------------------------------------------------------------------------

NTSTATUS
DfsDCSetVolumeState(
    IN const PDFS_PKT_ENTRY_ID VolumeId,
    IN const ULONG State)
{
    NTSTATUS                    status;
    HANDLE                      dfsHandle = NULL;
    DFS_SETSTATE_ARG            setStateArg;
    MARSHAL_BUFFER              marshalBuffer;
    PUCHAR                      buffer = NULL;
    ULONG                       size;

    status = DfsOpen( &dfsHandle, NULL );

    if (NT_SUCCESS(status)) {

        setStateArg.Id = *VolumeId;
        setStateArg.Type = State;

        size = 0;

        status = DfsRtlSize( &MiSetStateArg, &setStateArg, &size );

        if (NT_SUCCESS(status)) {

            buffer = (PUCHAR) malloc( size );

            if (buffer == NULL) {

                status = STATUS_INSUFFICIENT_RESOURCES;

            }

        }

        if (NT_SUCCESS(status)) {

            MarshalBufferInitialize( &marshalBuffer, size, buffer );

            status = DfsRtlPut( &
                        marshalBuffer,
                        &MiSetStateArg,
                        &setStateArg );

        }

        if (NT_SUCCESS(status)) {

            status = DfsFsctl(
                        dfsHandle,
                        FSCTL_DFS_DC_SET_VOLUME_STATE,
                        buffer,
                        size,
                        NULL,
                        0);

        }

        NtClose( dfsHandle );

        if (buffer != NULL) {

            free( buffer );

        }

    }

    return( status );

}

//+----------------------------------------------------------------------------
//
//  Function:   DfsSetVolumeTimeout
//
//  Synopsis:   Sets the timeout of a volume in the DCs.
//
//  Arguments:  [VolumeId] -- The volume on which to operate
//              [Timeout] -- Timeout, in seconds
//
//  Returns:    [STATUS_SUCCESS] -- The specified timeout was set as specified.
//
//              [DFS_STATUS_NO_SUCH_ENTRY] -- The specified volume was not
//                      found.
//
//              [STATUS_DATA_ERROR] -- marshalling or unmarshalling error.
//
//              [STATUS_INSUFFICIENT_RESOURCES] -- Out of memory situation.
//
//              Status from opening handle to the Dfs driver.
//
//-----------------------------------------------------------------------------

NTSTATUS
DfsSetVolumeTimeout(
    IN const PDFS_PKT_ENTRY_ID VolumeId,
    IN const ULONG Timeout)
{
    NTSTATUS                    status;
    HANDLE                      dfsHandle = NULL;
    DFS_SET_VOLUME_TIMEOUT_ARG  setVolTimeoutArg;
    MARSHAL_BUFFER              marshalBuffer;
    PUCHAR                      buffer = NULL;
    ULONG                       size;

    status = DfsOpen( &dfsHandle, NULL );

    if (NT_SUCCESS(status)) {

        setVolTimeoutArg.Id = *VolumeId;
        setVolTimeoutArg.Timeout = Timeout;

        size = 0;

        status = DfsRtlSize( &MiSetVolTimeoutArg, &setVolTimeoutArg, &size );

        if (NT_SUCCESS(status)) {

            buffer = (PUCHAR) malloc( size );

            if (buffer == NULL) {

                status = STATUS_INSUFFICIENT_RESOURCES;

            }

        }

        if (NT_SUCCESS(status)) {

            MarshalBufferInitialize( &marshalBuffer, size, buffer );

            status = DfsRtlPut( &
                        marshalBuffer,
                        &MiSetVolTimeoutArg,
                        &setVolTimeoutArg );

        }

        if (NT_SUCCESS(status)) {

            status = DfsFsctl(
                        dfsHandle,
                        FSCTL_DFS_SET_VOLUME_TIMEOUT,
                        buffer,
                        size,
                        NULL,
                        0);

        }

        NtClose( dfsHandle );

        if (buffer != NULL) {

            free( buffer );

        }

    }

    return( status );

}

//+----------------------------------------------------------------------------
//
//  Function:   DfsCreateSiteEntry
//
//  Synopsis:   Loads a Site entry into the dfs site table
//
//  Arguments:  [pInfoArg] -- DFS_CREATE_SITE_INFO_ARG with info to update
//
//  Returns:    Status from opening handle to the Dfs driver.
//
//-----------------------------------------------------------------------------

NTSTATUS
DfsCreateSiteEntry(
    PCHAR arg,
    ULONG size)
{
    NTSTATUS                    status;
    HANDLE                      dfsHandle = NULL;

    status = DfsOpen( &dfsHandle, NULL );

    if (NT_SUCCESS(status)) {


        status = DfsFsctl(
                    dfsHandle,
                    FSCTL_DFS_CREATE_SITE_INFO,
                    arg,
                    size,
                    NULL,
                    0);

        NtClose( dfsHandle );

    }

    return( status );
}

//+----------------------------------------------------------------------------
//
//  Function:   DfsDeleteSiteEntry
//
//  Synopsis:   Loads a Site entry into the dfs site table
//
//  Arguments:  [pInfoArg] -- DFS_DELETE_SITE_INFO_ARG with info to update
//
//  Returns:    Status from opening handle to the Dfs driver.
//
//-----------------------------------------------------------------------------

NTSTATUS
DfsDeleteSiteEntry(
    PCHAR arg,
    ULONG size)
{
    NTSTATUS                    status;
    HANDLE                      dfsHandle = NULL;

    status = DfsOpen( &dfsHandle, NULL );

    if (NT_SUCCESS(status)) {


        status = DfsFsctl(
                    dfsHandle,
                    FSCTL_DFS_DELETE_SITE_INFO,
                    arg,
                    size,
                    NULL,
                    0);

        NtClose( dfsHandle );

    }

    return( status );
}