windows-nt/Source/XPSP1/NT/base/fs/mup/provider.c

279 lines
7 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
//+----------------------------------------------------------------------------
//
// Copyright (C) 1992, Microsoft Corporation
//
// File: provider.c
//
// Contents: Module to initialize DFS driver providers.
//
// Classes:
//
// Functions: ProviderInit --
// DfsGetProviderForDevice
// DfsInsertProvider
//
// History: 12 Sep 1992 Milans created.
// 05 Apr 1993 Milans moved into driver.
//
//-----------------------------------------------------------------------------
#include "dfsprocs.h"
#include "rpselect.h"
#include "provider.h"
#define MAX_ENTRY_PATH 80 // Max. length of entry path
#define Dbg DEBUG_TRACE_INIT
#define prov_debug_out(x, y) DfsDbgTrace(0, Dbg, x, y)
#ifdef ALLOC_PRAGMA
#pragma alloc_text( PAGE, ProviderInit )
#pragma alloc_text( PAGE, DfsGetProviderForDevice )
#pragma alloc_text( PAGE, DfsInsertProvider )
#endif // ALLOC_PRAGMA
//+----------------------------------------------------------------------------
//
// Function: ProviderInit
//
// Synopsis: Initializes the provider list with
// - Local File service provider
// - Standard remote Cairo provider
// - Downlevel LanMan provider.
//
// Arguments: None
//
// Returns: STATUS_SUCCESS
//
//-----------------------------------------------------------------------------
NTSTATUS
ProviderInit(void)
{
NTSTATUS Status;
UNICODE_STRING ustrProviderName;
//
// Initialize the Dfs aware SMB provider
//
RtlInitUnicodeString(&ustrProviderName, DD_NFS_DEVICE_NAME_U);
Status = DfsInsertProvider(
&ustrProviderName,
PROV_DFS_RDR,
PROV_ID_DFS_RDR);
if (!NT_SUCCESS(Status))
return(Status);
RtlInitUnicodeString(&ustrProviderName, DD_MUP_DEVICE_NAME);
Status = DfsInsertProvider(
&ustrProviderName,
PROV_STRIP_PREFIX,
PROV_ID_MUP_RDR);
return( Status );
}
//+----------------------------------------------------------------------------
//
// Function: DfsGetProviderForDevice
//
// Synopsis: Retrieves a provider definition given a Device Name. If the
// provider definition does not exist, a new one is created and
// returned.
//
// This routine is meant for use in handling a STATUS_REPARSE
// returned by the MUP. Since only downlevel requests are sent
// to the MUP, this routine will always return a provider def
// that is marked as downlevel (ie, Capability has the
// PROV_STRIP_PREFIX bit set).
//
// Arguments: [DeviceName] -- Name of Device to look for.
//
// [Provider] -- On successful return, contains pointer to
// PROVIDER_DEF with given DeviceName.
//
// Returns: [STATUS_SUCCESS] -- Provider returned.
//
// [STATUS_INSUFFICIENT_RESOURCES] -- Out of memory condition.
//
// [STATUS_FS_DRIVER_REQUIRED] -- Don't have appropriate
// provider.
//
//-----------------------------------------------------------------------------
NTSTATUS
DfsGetProviderForDevice(
PUNICODE_STRING DeviceName,
PPROVIDER_DEF *Provider)
{
NTSTATUS status;
int i;
ExAcquireResourceExclusiveLite( &DfsData.Resource, TRUE );
*Provider = NULL;
for (i = 0; i < DfsData.cProvider && *Provider == NULL; i++) {
if ((DfsData.pProvider[i].DeviceName.Length == DeviceName->Length) &&
(DfsData.pProvider[i].fProvCapability & PROV_STRIP_PREFIX) != 0) {
if (RtlEqualUnicodeString(
&DfsData.pProvider[i].DeviceName,
DeviceName, TRUE)) {
*Provider = &DfsData.pProvider[i];
status = STATUS_SUCCESS;
break;
}
}
}
if (*Provider == NULL) {
//
// Attempt to create a new provider def
//
UNICODE_STRING ProviderName;
ProviderName.Length = DeviceName->Length;
ProviderName.MaximumLength = ProviderName.Length + sizeof(WCHAR);
ProviderName.Buffer = (PWCHAR) ExAllocatePoolWithTag(
PagedPool,
ProviderName.MaximumLength,
' puM');
if (ProviderName.Buffer != NULL) {
RtlZeroMemory(
ProviderName.Buffer,
ProviderName.MaximumLength);
RtlMoveMemory(
ProviderName.Buffer,
DeviceName->Buffer,
ProviderName.Length);
status = DfsInsertProvider(
&ProviderName,
PROV_STRIP_PREFIX,
i);
if (status == STATUS_SUCCESS) {
*Provider = &DfsData.pProvider[i];
} else {
ExFreePool( ProviderName.Buffer );
}
} else {
status = STATUS_INSUFFICIENT_RESOURCES;
}
}
ExReleaseResourceLite( &DfsData.Resource );
if (*Provider != NULL && (*Provider)->FileObject == NULL) {
//
// We found (or created) a provider definition that is
//
*Provider = ReplLookupProvider( i );
if (*Provider == NULL)
status = STATUS_FS_DRIVER_REQUIRED;
}
return( status );
}
//+----------------------------------------------------------------------------
//
// Function: DfsInsertProvider
//
// Synopsis: Given a provider name, id, and capability, will add a new or
// overwrite an existing provider definition.
//
// Arguments:
//
// Returns:
//
//-----------------------------------------------------------------------------
NTSTATUS DfsInsertProvider(
IN PUNICODE_STRING ProviderName,
IN ULONG fProvCapability,
IN ULONG eProviderId)
{
PPROVIDER_DEF pProv = DfsData.pProvider;
int iProv;
//
// Find a free provider structure, or overwrite an existing one.
//
for (iProv = 0; iProv < DfsData.cProvider; iProv++, pProv++) {
if (pProv->eProviderId == eProviderId)
break;
}
if (iProv >= DfsData.maxProvider) {
ASSERT(iProv >= DfsData.maxProvider && "Out of provider structs");
return(STATUS_INSUFFICIENT_RESOURCES);
}
if (iProv < DfsData.cProvider) {
//
// Decrement reference counts on saved objects
//
if (pProv->FileObject)
ObDereferenceObject(pProv->FileObject);
if (pProv->DeviceObject)
ObDereferenceObject(pProv->DeviceObject);
if (pProv->DeviceName.Buffer)
ExFreePool(pProv->DeviceName.Buffer);
}
pProv->FileObject = NULL;
pProv->DeviceObject = NULL;
pProv->eProviderId = (USHORT) eProviderId;
pProv->fProvCapability = (USHORT) fProvCapability;
pProv->DeviceName = *ProviderName;
if (iProv == DfsData.cProvider) {
DfsData.cProvider++;
}
return(STATUS_SUCCESS);
}