279 lines
7 KiB
C
279 lines
7 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_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);
|
|||
|
}
|
|||
|
|
|||
|
|