274 lines
6.9 KiB
C
274 lines
6.9 KiB
C
//+----------------------------------------------------------------------------
|
||
//
|
||
// 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_LM_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;
|
||
|
||
ExAcquireResourceExclusive( &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) ExAllocatePool(
|
||
PagedPool,
|
||
ProviderName.MaximumLength);
|
||
|
||
if (ProviderName.Buffer != NULL) {
|
||
|
||
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;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
ExReleaseResource( &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);
|
||
}
|
||
|
||
|