2605 lines
77 KiB
C
2605 lines
77 KiB
C
/*++
|
||
|
||
Copyright (c) 1989 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
Init.c
|
||
|
||
Abstract:
|
||
|
||
This module implements the DRIVER_INITIALIZATION routine for the SMB mini rdr.
|
||
|
||
Author:
|
||
|
||
Balan Sethu Raman [SethuR] 7-Mar-1995
|
||
|
||
Revision History:
|
||
|
||
|
||
--*/
|
||
|
||
#include "precomp.h"
|
||
#pragma hdrstop
|
||
#include "ntverp.h"
|
||
#include "ntbowsif.h"
|
||
#include <bowpub.h>
|
||
#include "netevent.h"
|
||
#include "nvisible.h"
|
||
#include <ntddbrow.h>
|
||
|
||
BOOL IsTerminalServicesServer();
|
||
|
||
|
||
#define RDBSS_DRIVER_LOAD_STRING L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Rdbss"
|
||
|
||
#ifdef ALLOC_PRAGMA
|
||
#pragma alloc_text(PAGE, DriverEntry)
|
||
#pragma alloc_text(PAGE, MRxSmbInitUnwind)
|
||
#pragma alloc_text(PAGE, MRxSmbInitUnwindSmb)
|
||
#pragma alloc_text(PAGE, MRxSmbInitUnwindBowser)
|
||
#pragma alloc_text(PAGE, MRxSmbUnload)
|
||
#pragma alloc_text(PAGE, MRxSmbInitializeTables)
|
||
#pragma alloc_text(PAGE, MRxSmbStart)
|
||
#pragma alloc_text(PAGE, MRxSmbStop)
|
||
#pragma alloc_text(PAGE, MRxSmbInitializeSecurity)
|
||
#pragma alloc_text(PAGE, MRxSmbUninitializeSecurity)
|
||
#pragma alloc_text(PAGE, MRxSmbReadMiscellaneousRegistryParameters)
|
||
#pragma alloc_text(PAGE, SmbCeGetConfigurationInformation)
|
||
#pragma alloc_text(PAGE, MRxSmbFsdDispatch)
|
||
#pragma alloc_text(PAGE, MRxSmbDeallocateForFcb)
|
||
#pragma alloc_text(PAGE, MRxSmbDeallocateForFobx)
|
||
#pragma alloc_text(PAGE, MRxSmbGetUlongRegistryParameter)
|
||
#pragma alloc_text(PAGE, MRxSmbPreUnload)
|
||
#pragma alloc_text(PAGE, IsTerminalServicesServer)
|
||
#endif
|
||
|
||
extern ERESOURCE s_SmbCeDbResource;
|
||
extern ERESOURCE s_SmbSecuritySignatureResource;
|
||
|
||
NTSYSAPI
|
||
NTSTATUS
|
||
NTAPI
|
||
ZwLoadDriver(
|
||
IN PUNICODE_STRING DriverServiceName
|
||
);
|
||
|
||
//
|
||
// Global data declarations .
|
||
//
|
||
|
||
PVOID MRxSmbPoRegistrationState = NULL;
|
||
|
||
FAST_MUTEX MRxSmbSerializationMutex;
|
||
FAST_MUTEX MRxSmbReadWriteMutex;
|
||
|
||
MRXSMB_CONFIGURATION MRxSmbConfiguration;
|
||
|
||
MRXSMB_STATE MRxSmbState = MRXSMB_STARTABLE;
|
||
|
||
SMBCE_CONTEXT SmbCeContext;
|
||
PMDL s_pEchoSmbMdl = NULL;
|
||
ULONG s_EchoSmbLength = 0;
|
||
|
||
BOOLEAN EnablePlainTextPassword = FALSE;
|
||
BOOLEAN SetupInProgress = FALSE;
|
||
BOOLEAN EnableWmiLog = FALSE;
|
||
BOOLEAN Win9xSessionRestriction = FALSE;
|
||
ULONG OffLineFileTimeoutInterval = 1000; // in seconds
|
||
ULONG ExtendedSessTimeoutInterval = 1000; // in seconds
|
||
ULONG MaxNumOfExchangesForPipelineReadWrite = 8;
|
||
|
||
#ifdef EXPLODE_POOLTAGS
|
||
ULONG MRxSmbExplodePoolTags = 1;
|
||
#else
|
||
ULONG MRxSmbExplodePoolTags = 0;
|
||
#endif
|
||
|
||
//
|
||
// This counts any SMBs sent out which could make the contents of the Get
|
||
// File Attributes cache stale.
|
||
//
|
||
ULONG NameCacheGFAInvalidate;
|
||
|
||
// local functions forward declarations
|
||
|
||
NTSTATUS
|
||
MRxSmbDeleteRegistryParameter(
|
||
HANDLE ParametersHandle,
|
||
PWCHAR ParameterName
|
||
);
|
||
//
|
||
// Mini Redirector global variables.
|
||
//
|
||
|
||
struct _MINIRDR_DISPATCH MRxSmbDispatch;
|
||
|
||
PRDBSS_DEVICE_OBJECT MRxSmbDeviceObject;
|
||
|
||
MRXSMB_GLOBAL_PADDING MrxSmbCeGlobalPadding;
|
||
|
||
LIST_ENTRY ExchangesWaitingForServerResponseBuffer;
|
||
LONG NumOfBuffersForServerResponseInUse;
|
||
|
||
BOOLEAN MRxSmbEnableCompression = FALSE;
|
||
BOOLEAN MRxSmbSecuritySignaturesRequired = FALSE;
|
||
BOOLEAN MRxSmbSecuritySignaturesEnabled = TRUE;
|
||
BOOLEAN MRxSmbEnableCachingOnWriteOnlyOpens = FALSE;
|
||
BOOLEAN MRxSmbEnableDownLevelLogOff = FALSE;
|
||
|
||
ULONG MRxSmbConnectionIdLevel = 0;
|
||
|
||
BOOLEAN UniqueFileNames = FALSE;
|
||
BOOLEAN DisableByteRangeLockingOnReadOnlyFiles = FALSE;
|
||
|
||
FAST_MUTEX MRxSmbFileInfoCacheLock;
|
||
|
||
//
|
||
// The following variable controls whether clientside cacheing is enabled or not.
|
||
// It is the responsibility of the Csc routines themselves to do the right things
|
||
// is CSC is not enabled because we will make the calls anyway.
|
||
//
|
||
|
||
BOOLEAN MRxSmbIsCscEnabled = TRUE;
|
||
BOOLEAN MRxSmbIsCscEnabledForDisconnected = TRUE;
|
||
BOOLEAN MRxSmbCscTransitionEnabledByDefault = FALSE;
|
||
BOOLEAN MRxSmbEnableDisconnectedRB = FALSE; // don't transition remoteboot machine to disconnected state
|
||
BOOLEAN MRxSmbCscAutoDialEnabled = FALSE;
|
||
//
|
||
// If this flag is TRUE, we strictly obey the transport binding order. If it is FALSE,
|
||
// we can use whatever transport we want to connect to the remote server.
|
||
//
|
||
BOOLEAN MRxSmbObeyBindingOrder = FALSE;
|
||
|
||
ULONG MRxSmbBuildNumber = VER_PRODUCTBUILD;
|
||
#ifdef RX_PRIVATE_BUILD
|
||
ULONG MRxSmbPrivateBuild = 1;
|
||
#else
|
||
ULONG MRxSmbPrivateBuild = 0;
|
||
#endif
|
||
|
||
//
|
||
// MRxSmbSecurityInitialized indicates whether MRxSmbInitializeSecurity
|
||
// has been called.
|
||
//
|
||
|
||
BOOLEAN MRxSmbSecurityInitialized = FALSE;
|
||
|
||
//
|
||
// MRxSmbBootedRemotely indicates that the machine did a remote boot.
|
||
//
|
||
|
||
BOOLEAN MRxSmbBootedRemotely = FALSE;
|
||
|
||
//
|
||
// MRxSmbUseKernelSecurity indicates that the machine should use kernel mode security APIs
|
||
// during this remote boot boot.
|
||
//
|
||
|
||
BOOLEAN MRxSmbUseKernelModeSecurity = FALSE;
|
||
|
||
|
||
LIST_ENTRY MRxSmbPagingFilesSrvOpenList;
|
||
|
||
//
|
||
// These variables will, in the near future, be passed from the kernel to the
|
||
// redirector to tell it which share is the remote boot share and how to log on
|
||
// to the server.
|
||
//
|
||
|
||
PKEY_VALUE_PARTIAL_INFORMATION MRxSmbRemoteBootRootValue = NULL;
|
||
PKEY_VALUE_PARTIAL_INFORMATION MRxSmbRemoteBootMachineDirectoryValue = NULL;
|
||
UNICODE_STRING MRxSmbRemoteBootShare;
|
||
UNICODE_STRING MRxSmbRemoteBootPath;
|
||
UNICODE_STRING MRxSmbRemoteSetupPath;
|
||
UNICODE_STRING MRxSmbRemoteBootMachineName;
|
||
UNICODE_STRING MRxSmbRemoteBootMachinePassword;
|
||
UNICODE_STRING MRxSmbRemoteBootMachineDomain;
|
||
UCHAR MRxSmbRemoteBootMachineSid[RI_SECRET_SID_SIZE];
|
||
RI_SECRET MRxSmbRemoteBootSecret;
|
||
#if defined(REMOTE_BOOT)
|
||
BOOLEAN MRxSmbRemoteBootSecretValid = FALSE;
|
||
BOOLEAN MRxSmbRemoteBootDoMachineLogon;
|
||
BOOLEAN MRxSmbRemoteBootUsePassword2;
|
||
#endif // defined(REMOTE_BOOT)
|
||
|
||
//
|
||
// for LoopBack detection
|
||
//
|
||
GUID CachedServerGuid;
|
||
|
||
UNICODE_STRING MRxSmbRemoteBootRedirectionPrefix;
|
||
UNICODE_PREFIX_TABLE MRxSmbRemoteBootRedirectionTable;
|
||
|
||
//declare the shadow debugtrace controlpoints
|
||
|
||
RXDT_DefineCategory(CREATE);
|
||
RXDT_DefineCategory(CLEANUP);
|
||
RXDT_DefineCategory(CLOSE);
|
||
RXDT_DefineCategory(READ);
|
||
RXDT_DefineCategory(WRITE);
|
||
RXDT_DefineCategory(LOCKCTRL);
|
||
RXDT_DefineCategory(FLUSH);
|
||
RXDT_DefineCategory(PREFIX);
|
||
RXDT_DefineCategory(FCBSTRUCTS);
|
||
RXDT_DefineCategory(DISPATCH);
|
||
RXDT_DefineCategory(EA);
|
||
RXDT_DefineCategory(DEVFCB);
|
||
RXDT_DefineCategory(DISCCODE); //this shouldn't be a shadow
|
||
RXDT_DefineCategory(BROWSER); //this shouldn't be a shadow
|
||
RXDT_DefineCategory(CONNECT); //this shouldn't be a shadow
|
||
|
||
typedef enum _MRXSMB_INIT_STATES {
|
||
MRXSMBINIT_ALL_INITIALIZATION_COMPLETED,
|
||
MRXSMBINIT_STARTED_BROWSER,
|
||
MRXSMBINIT_INITIALIZED_FOR_CSC,
|
||
MRXSMBINIT_MINIRDR_REGISTERED,
|
||
MRXSMBINIT_START
|
||
} MRXSMB_INIT_STATES;
|
||
|
||
|
||
|
||
NTSTATUS
|
||
MRxSmbFsdDispatch (
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PIRP Irp
|
||
);
|
||
|
||
NTSTATUS
|
||
MRxSmbCheckTransportName(
|
||
IN PIRP Irp,
|
||
OUT PSMBCEDB_SERVER_ENTRY *ppServerEntry
|
||
);
|
||
|
||
NTSTATUS
|
||
SmbCeGetServersWithExtendedSessTimeout();
|
||
|
||
NTSTATUS
|
||
DriverEntry(
|
||
IN PDRIVER_OBJECT DriverObject,
|
||
IN PUNICODE_STRING RegistryPath
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This is the initialization routine for the SMB mini redirector
|
||
|
||
Arguments:
|
||
|
||
DriverObject - Pointer to driver object created by the system.
|
||
|
||
Return Value:
|
||
|
||
RXSTATUS - The function value is the final status from the initialization
|
||
operation.
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS Status;
|
||
MRXSMB_INIT_STATES MRxSmbInitState = 0;
|
||
UNICODE_STRING SmbMiniRedirectorName;
|
||
|
||
PAGED_CODE();
|
||
|
||
#ifdef MONOLITHIC_MINIRDR
|
||
DbgPrint("InitWrapper\n");
|
||
Status = RxDriverEntry(DriverObject, RegistryPath);
|
||
DbgPrint("BackFromInitWrapper %p\n",Status);
|
||
if (Status != STATUS_SUCCESS) {
|
||
DbgPrint("Wrapper failed to initialize. Status = %08lx\n",Status);
|
||
return(Status);
|
||
}
|
||
#endif
|
||
|
||
NameCacheGFAInvalidate = 0;
|
||
|
||
RtlZeroMemory(&MRxSmbStatistics,sizeof(MRxSmbStatistics));
|
||
KeQuerySystemTime(&MRxSmbStatistics.StatisticsStartTime);
|
||
RtlZeroMemory(&MrxSmbCeGlobalPadding,sizeof(MrxSmbCeGlobalPadding));
|
||
MmInitializeMdl(&MrxSmbCeGlobalPadding.Mdl,&MrxSmbCeGlobalPadding.Pad[0],SMBCE_PADDING_DATA_SIZE);
|
||
MmBuildMdlForNonPagedPool(&MrxSmbCeGlobalPadding.Mdl);
|
||
|
||
ExInitializeFastMutex(&MRxSmbSerializationMutex);
|
||
ExInitializeFastMutex(&MRxSmbReadWriteMutex);
|
||
|
||
Status = MRxSmbInitializeTransport();
|
||
if (Status != STATUS_SUCCESS) {
|
||
RxDbgTrace( 0, (DEBUG_TRACE_ALWAYS), ("MRxSmbDriverEntry failed to init transport data structures: %08lx\n", Status ));
|
||
return(STATUS_UNSUCCESSFUL);
|
||
}
|
||
|
||
MRxSmbReadMiscellaneousRegistryParameters();
|
||
|
||
try {
|
||
|
||
//
|
||
// Initialize the discardable code functions before doing anything else.
|
||
//
|
||
|
||
RdrInitializeDiscardableCode();
|
||
|
||
|
||
MRxSmbInitState = MRXSMBINIT_START;
|
||
|
||
RtlInitUnicodeString(&SmbMiniRedirectorName,DD_NFS_DEVICE_NAME_U);
|
||
RxDbgTrace( 0, (DEBUG_TRACE_ALWAYS), ("MRxSmbDriverEntry: DriverObject =%p\n", DriverObject ));
|
||
|
||
Status = RxRegisterMinirdr(&MRxSmbDeviceObject,
|
||
DriverObject,
|
||
&MRxSmbDispatch,
|
||
0, //register with unc and for mailslots
|
||
&SmbMiniRedirectorName,
|
||
0, //IN ULONG DeviceExtensionSize,
|
||
FILE_DEVICE_NETWORK_FILE_SYSTEM, //IN DEVICE_TYPE DeviceType,
|
||
FILE_REMOTE_DEVICE //IN ULONG DeviceCharacteristics
|
||
);
|
||
if (Status!=STATUS_SUCCESS) {
|
||
RxDbgTrace( 0, (DEBUG_TRACE_ALWAYS), ("MRxSmbDriverEntry failed: %08lx\n", Status ));
|
||
try_return(Status);
|
||
}
|
||
|
||
MRxSmbInitState = MRXSMBINIT_MINIRDR_REGISTERED;
|
||
|
||
Status = MRxSmbInitializeCSC(&SmbMiniRedirectorName);
|
||
if (!NT_SUCCESS( Status )) {
|
||
try_return( Status );
|
||
}
|
||
MRxSmbInitState = MRXSMBINIT_INITIALIZED_FOR_CSC;
|
||
|
||
// init the browser.....BUT DONT TRUST IT!!!!
|
||
|
||
try {
|
||
|
||
// Setup the browser
|
||
Status = BowserDriverEntry(DriverObject, RegistryPath);
|
||
|
||
} except(EXCEPTION_EXECUTE_HANDLER) {
|
||
|
||
// We had some trouble trying to start up the browser.....sigh.
|
||
|
||
Status = GetExceptionCode();
|
||
DbgPrint("Browser didn't start....%08lx\n", Status);
|
||
|
||
}
|
||
|
||
if (!NT_SUCCESS( Status )) {
|
||
try_return( Status );
|
||
}
|
||
|
||
MRxSmbInitState = MRXSMBINIT_STARTED_BROWSER;
|
||
|
||
//for all this stuff, there's no undo.....so no extra state
|
||
|
||
Status = MRxSmbInitializeTables();
|
||
if (!NT_SUCCESS( Status )) {
|
||
try_return(Status);
|
||
}
|
||
|
||
RtlInitUnicodeString(&SmbCeContext.ComputerName,NULL);
|
||
RtlInitUnicodeString(&SmbCeContext.DomainName,NULL);
|
||
RtlInitUnicodeString(&SmbCeContext.OperatingSystem, NULL);
|
||
RtlInitUnicodeString(&SmbCeContext.LanmanType, NULL);
|
||
RtlInitUnicodeString(&SmbCeContext.Transports, NULL);
|
||
RtlInitUnicodeString(&SmbCeContext.ServersWithExtendedSessTimeout, NULL);
|
||
RtlInitUnicodeString(&MRxSmbRemoteBootMachineName, NULL);
|
||
RtlInitUnicodeString(&MRxSmbRemoteBootMachineDomain, NULL);
|
||
RtlInitUnicodeString(&MRxSmbRemoteBootMachinePassword, NULL);
|
||
|
||
SmbCeGetConfigurationInformation();
|
||
SmbCeGetServersWithExtendedSessTimeout();
|
||
|
||
try_exit: NOTHING;
|
||
} finally {
|
||
if (Status != STATUS_SUCCESS) {
|
||
MRxSmbInitUnwind(DriverObject,MRxSmbInitState);
|
||
}
|
||
}
|
||
if (Status != STATUS_SUCCESS) {
|
||
DbgPrint("MRxSmb failed to start with %08lx %08lx\n",Status,MRxSmbInitState);
|
||
return(Status);
|
||
}
|
||
|
||
|
||
// Do not setup Unload Routine. This prevents mrxsmb from being unloaded individually
|
||
|
||
//setup the driverdispatch for people who come in here directly....like the browser
|
||
//CODE.IMPROVEMENT we should change this code so that the things that aren't examined
|
||
// in MRxSmbFsdDispatch are routed directly, i.e. reads and writes
|
||
{ULONG i;
|
||
for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) {
|
||
DriverObject->MajorFunction[i] = (PDRIVER_DISPATCH)MRxSmbFsdDispatch;
|
||
}}
|
||
|
||
Status = IoWMIRegistrationControl ((PDEVICE_OBJECT)MRxSmbDeviceObject, WMIREG_ACTION_REGISTER);
|
||
|
||
if (Status != STATUS_SUCCESS) {
|
||
DbgPrint("MRxSmb fails to register WMI %lx\n",Status);
|
||
} else {
|
||
EnableWmiLog = TRUE;
|
||
}
|
||
|
||
//and get out
|
||
return STATUS_SUCCESS;
|
||
|
||
}
|
||
|
||
|
||
|
||
VOID
|
||
MRxSmbPreUnload(
|
||
VOID
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
|
||
Arguments:
|
||
|
||
|
||
Return Value:
|
||
|
||
|
||
Notes:
|
||
|
||
--*/
|
||
{
|
||
PDRIVER_OBJECT DriverObject = ((PDEVICE_OBJECT)MRxSmbDeviceObject)->DriverObject;
|
||
|
||
PAGED_CODE();
|
||
|
||
if (EnableWmiLog) {
|
||
NTSTATUS Status;
|
||
|
||
Status = IoWMIRegistrationControl ((PDEVICE_OBJECT)MRxSmbDeviceObject, WMIREG_ACTION_DEREGISTER);
|
||
if (Status != STATUS_SUCCESS) {
|
||
DbgPrint("MRxSmb fails to deregister WMI %lx\n",Status);
|
||
}
|
||
}
|
||
|
||
//ASSERT(!"Starting to unload!");
|
||
//RxUnregisterMinirdr(MRxSmbDeviceObject);
|
||
MRxSmbInitUnwindSmb(DriverObject, MRXSMBINIT_ALL_INITIALIZATION_COMPLETED);
|
||
|
||
// free the pool associated with the resource
|
||
ExDeleteResource(&s_SmbCeDbResource);
|
||
ExDeleteResource(&s_SmbSecuritySignatureResource);
|
||
|
||
RxDbgTrace( 0, (DEBUG_TRACE_ALWAYS), ("MRxSmbPreUnload exit: DriverObject =%p\n", DriverObject) );
|
||
}
|
||
|
||
|
||
VOID
|
||
MRxSmbInitUnwind(
|
||
IN PDRIVER_OBJECT DriverObject,
|
||
IN MRXSMB_INIT_STATES MRxSmbInitState
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine does the common uninit work for unwinding from a bad driver entry or for unloading.
|
||
|
||
Arguments:
|
||
|
||
RxInitState - tells how far we got into the intialization
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
{
|
||
PAGED_CODE();
|
||
|
||
MRxSmbInitUnwindSmb(DriverObject, MRxSmbInitState);
|
||
MRxSmbInitUnwindBowser(DriverObject, MRxSmbInitState);
|
||
}
|
||
|
||
VOID
|
||
MRxSmbInitUnwindSmb(
|
||
IN PDRIVER_OBJECT DriverObject,
|
||
IN MRXSMB_INIT_STATES MRxSmbInitState
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine does the common uninit work for SMB for unwinding from a bad driver entry or for unloading.
|
||
|
||
Arguments:
|
||
|
||
RxInitState - tells how far we got into the intialization
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
|
||
{
|
||
PAGED_CODE();
|
||
|
||
switch (MRxSmbInitState) {
|
||
case MRXSMBINIT_ALL_INITIALIZATION_COMPLETED:
|
||
//Nothing extra to do...this is just so that the constant in RxUnload doesn't change.......
|
||
//lack of break intentional
|
||
|
||
|
||
#ifdef MRXSMB_BUILD_FOR_CSC
|
||
case MRXSMBINIT_INITIALIZED_FOR_CSC:
|
||
MRxSmbUninitializeCSC();
|
||
//lack of break intentional
|
||
#endif
|
||
|
||
|
||
case MRXSMBINIT_MINIRDR_REGISTERED:
|
||
RxUnregisterMinirdr(MRxSmbDeviceObject);
|
||
//lack of break intentional
|
||
|
||
}
|
||
|
||
}
|
||
|
||
VOID
|
||
MRxSmbInitUnwindBowser(
|
||
IN PDRIVER_OBJECT DriverObject,
|
||
IN MRXSMB_INIT_STATES MRxSmbInitState
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine does the common uninit work for bowser for unwinding from a bad driver entry or for unloading.
|
||
|
||
Arguments:
|
||
|
||
RxInitState - tells how far we got into the intialization
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
switch (MRxSmbInitState) {
|
||
case MRXSMBINIT_ALL_INITIALIZATION_COMPLETED:
|
||
case MRXSMBINIT_STARTED_BROWSER:
|
||
BowserUnload(DriverObject);
|
||
case MRXSMBINIT_START:
|
||
RdrUninitializeDiscardableCode();
|
||
break;
|
||
}
|
||
}
|
||
|
||
VOID
|
||
MRxSmbUnload(
|
||
IN PDRIVER_OBJECT DriverObject
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This is the unload routine for the SMB mini redirector.
|
||
|
||
Arguments:
|
||
|
||
DriverObject - pointer to the driver object for the MRxSmb
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
|
||
{
|
||
PAGED_CODE();
|
||
|
||
RxDbgTrace( 0, (DEBUG_TRACE_ALWAYS), ("MRxSmbUnload: DriverObject =%p\n", DriverObject) );
|
||
MRxSmbInitUnwindBowser(DriverObject,MRXSMBINIT_ALL_INITIALIZATION_COMPLETED);
|
||
}
|
||
|
||
|
||
|
||
NTSTATUS
|
||
MRxSmbInitializeTables(
|
||
void
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine sets up the mini redirector dispatch vector and also calls to initialize any other tables needed.
|
||
|
||
Return Value:
|
||
|
||
RXSTATUS - The return status for the operation
|
||
|
||
--*/
|
||
{
|
||
PAGED_CODE();
|
||
|
||
// Ensure that the SMB mini redirector context satisfies the size constraints
|
||
ASSERT(sizeof(MRXSMB_RX_CONTEXT) <= MRX_CONTEXT_SIZE);
|
||
|
||
//local minirdr dispatch table init
|
||
ZeroAndInitializeNodeType( &MRxSmbDispatch, RDBSS_NTC_MINIRDR_DISPATCH, sizeof(MINIRDR_DISPATCH));
|
||
|
||
// SMB mini redirector extension sizes and allocation policies.
|
||
// CODE.IMPROVEMENT -- currently we do not allocate the NET_ROOT and SRV_CALL extensions
|
||
// in the wrapper. Except for V_NET_ROOT wherein it is shared across multiple instances in
|
||
// the wrapper all the other data structure management should be left to the wrappers
|
||
|
||
MRxSmbDispatch.MRxFlags = (RDBSS_MANAGE_FCB_EXTENSION |
|
||
RDBSS_MANAGE_SRV_OPEN_EXTENSION |
|
||
RDBSS_MANAGE_FOBX_EXTENSION);
|
||
|
||
MRxSmbDispatch.MRxSrvCallSize = 0;
|
||
MRxSmbDispatch.MRxNetRootSize = 0;
|
||
MRxSmbDispatch.MRxVNetRootSize = 0;
|
||
MRxSmbDispatch.MRxFcbSize = sizeof(MRX_SMB_FCB);
|
||
MRxSmbDispatch.MRxSrvOpenSize = sizeof(MRX_SMB_SRV_OPEN);
|
||
MRxSmbDispatch.MRxFobxSize = sizeof(MRX_SMB_FOBX);
|
||
|
||
// Mini redirector cancel routine ..
|
||
MRxSmbDispatch.MRxCancel = NULL;
|
||
|
||
// Mini redirector Start/Stop
|
||
MRxSmbDispatch.MRxStart = MRxSmbStart;
|
||
MRxSmbDispatch.MRxStop = MRxSmbStop;
|
||
MRxSmbDispatch.MRxDevFcbXXXControlFile = MRxSmbDevFcbXXXControlFile;
|
||
|
||
// Mini redirector name resolution
|
||
MRxSmbDispatch.MRxCreateSrvCall = MRxSmbCreateSrvCall;
|
||
MRxSmbDispatch.MRxSrvCallWinnerNotify = MRxSmbSrvCallWinnerNotify;
|
||
MRxSmbDispatch.MRxCreateVNetRoot = MRxSmbCreateVNetRoot;
|
||
MRxSmbDispatch.MRxUpdateNetRootState = MRxSmbUpdateNetRootState;
|
||
MRxSmbDispatch.MRxExtractNetRootName = MRxSmbExtractNetRootName;
|
||
MRxSmbDispatch.MRxFinalizeSrvCall = MRxSmbFinalizeSrvCall;
|
||
MRxSmbDispatch.MRxFinalizeNetRoot = MRxSmbFinalizeNetRoot;
|
||
MRxSmbDispatch.MRxFinalizeVNetRoot = MRxSmbFinalizeVNetRoot;
|
||
|
||
// File System Object Creation/Deletion.
|
||
MRxSmbDispatch.MRxCreate = MRxSmbCreate;
|
||
MRxSmbDispatch.MRxCollapseOpen = MRxSmbCollapseOpen;
|
||
MRxSmbDispatch.MRxShouldTryToCollapseThisOpen = MRxSmbShouldTryToCollapseThisOpen;
|
||
MRxSmbDispatch.MRxExtendForCache = MRxSmbExtendForCache;
|
||
MRxSmbDispatch.MRxExtendForNonCache = MRxSmbExtendForNonCache;
|
||
MRxSmbDispatch.MRxTruncate = MRxSmbTruncate;
|
||
MRxSmbDispatch.MRxCleanupFobx = MRxSmbCleanupFobx;
|
||
MRxSmbDispatch.MRxCloseSrvOpen = MRxSmbCloseSrvOpen;
|
||
MRxSmbDispatch.MRxFlush = MRxSmbFlush;
|
||
MRxSmbDispatch.MRxForceClosed = MRxSmbForcedClose;
|
||
MRxSmbDispatch.MRxDeallocateForFcb = MRxSmbDeallocateForFcb;
|
||
MRxSmbDispatch.MRxDeallocateForFobx = MRxSmbDeallocateForFobx;
|
||
MRxSmbDispatch.MRxIsLockRealizable = MRxSmbIsLockRealizable;
|
||
MRxSmbDispatch.MRxAreFilesAliased = MRxSmbAreFilesAliased;
|
||
|
||
// File System Objects query/Set
|
||
MRxSmbDispatch.MRxQueryDirectory = MRxSmbQueryDirectory;
|
||
MRxSmbDispatch.MRxQueryVolumeInfo = MRxSmbQueryVolumeInformation;
|
||
MRxSmbDispatch.MRxSetVolumeInfo = MRxSmbSetVolumeInformation;
|
||
MRxSmbDispatch.MRxQueryEaInfo = MRxSmbQueryEaInformation;
|
||
MRxSmbDispatch.MRxSetEaInfo = MRxSmbSetEaInformation;
|
||
MRxSmbDispatch.MRxQuerySdInfo = MRxSmbQuerySecurityInformation;
|
||
MRxSmbDispatch.MRxSetSdInfo = MRxSmbSetSecurityInformation;
|
||
MRxSmbDispatch.MRxQueryQuotaInfo = MRxSmbQueryQuotaInformation;
|
||
MRxSmbDispatch.MRxSetQuotaInfo = MRxSmbSetQuotaInformation;
|
||
MRxSmbDispatch.MRxQueryFileInfo = MRxSmbQueryFileInformation;
|
||
MRxSmbDispatch.MRxSetFileInfo = MRxSmbSetFileInformation;
|
||
MRxSmbDispatch.MRxSetFileInfoAtCleanup
|
||
= MRxSmbSetFileInformationAtCleanup;
|
||
MRxSmbDispatch.MRxIsValidDirectory= MRxSmbIsValidDirectory;
|
||
|
||
|
||
// Buffering state change
|
||
MRxSmbDispatch.MRxComputeNewBufferingState = MRxSmbComputeNewBufferingState;
|
||
|
||
// New MRX functions
|
||
MRxSmbDispatch.MRxPreparseName = MRxSmbPreparseName;
|
||
|
||
// File System Object I/O
|
||
MRxSmbDispatch.MRxLowIOSubmit[LOWIO_OP_READ] = MRxSmbRead;
|
||
MRxSmbDispatch.MRxLowIOSubmit[LOWIO_OP_WRITE] = MRxSmbWrite;
|
||
MRxSmbDispatch.MRxLowIOSubmit[LOWIO_OP_SHAREDLOCK] = MRxSmbLocks;
|
||
MRxSmbDispatch.MRxLowIOSubmit[LOWIO_OP_EXCLUSIVELOCK] = MRxSmbLocks;
|
||
MRxSmbDispatch.MRxLowIOSubmit[LOWIO_OP_UNLOCK] = MRxSmbLocks;
|
||
MRxSmbDispatch.MRxLowIOSubmit[LOWIO_OP_UNLOCK_MULTIPLE] = MRxSmbLocks;
|
||
MRxSmbDispatch.MRxLowIOSubmit[LOWIO_OP_FSCTL] = MRxSmbFsCtl;
|
||
MRxSmbDispatch.MRxLowIOSubmit[LOWIO_OP_IOCTL] = MRxSmbIoCtl;
|
||
//CODE.IMPROVEMENT shouldn't flush come thru lowio???
|
||
MRxSmbDispatch.MRxLowIOSubmit[LOWIO_OP_NOTIFY_CHANGE_DIRECTORY] = MRxSmbNotifyChangeDirectory;
|
||
|
||
//no longer a field MRxSmbDispatch.MRxUnlockRoutine = MRxSmbUnlockRoutine;
|
||
|
||
|
||
// Miscellanous
|
||
MRxSmbDispatch.MRxCompleteBufferingStateChangeRequest = MRxSmbCompleteBufferingStateChangeRequest;
|
||
MRxSmbDispatch.MRxGetConnectionId = MRxSmbGetConnectionId;
|
||
|
||
// initialize the paging file list
|
||
InitializeListHead(&MRxSmbPagingFilesSrvOpenList);
|
||
|
||
// The list contains the exchanges waiting on pre-allcate buffer in case of Security
|
||
// Signature checking is actived and no more buffer can be allocated
|
||
InitializeListHead(&ExchangesWaitingForServerResponseBuffer);
|
||
NumOfBuffersForServerResponseInUse = 0;
|
||
|
||
// initialize the mutex which protect the file info cache expire timer
|
||
ExInitializeFastMutex(&MRxSmbFileInfoCacheLock);
|
||
|
||
//
|
||
// now callout to initialize other tables
|
||
SmbPseInitializeTables();
|
||
|
||
return(STATUS_SUCCESS);
|
||
}
|
||
|
||
BOOLEAN AlreadyStarted = FALSE;
|
||
|
||
NTSTATUS
|
||
MRxSmbStart(
|
||
PRX_CONTEXT RxContext,
|
||
IN OUT PRDBSS_DEVICE_OBJECT RxDeviceObject
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine completes the initialization of the mini redirector fromn the
|
||
RDBSS perspective. Note that this is different from the initialization done
|
||
in DriverEntry. Any initialization that depends on RDBSS should be done as
|
||
part of this routine while the initialization that is independent of RDBSS
|
||
should be done in the DriverEntry routine.
|
||
|
||
Arguments:
|
||
|
||
RxContext - Supplies the Irp that was used to startup the rdbss
|
||
|
||
Return Value:
|
||
|
||
RXSTATUS - The return status for the operation
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS Status;
|
||
MRXSMB_STATE CurrentState;
|
||
|
||
PAGED_CODE();
|
||
|
||
//
|
||
// If this is a normal start (from the workstation service), change state from
|
||
// START_IN_PROGRESS to STARTED. If this is a remote boot start (from ioinit),
|
||
// don't change state. This is necessary to allow the workstation service to
|
||
// initialize correctly when it finally comes up.
|
||
//
|
||
|
||
if (RxContext->LowIoContext.ParamsFor.FsCtl.FsControlCode == FSCTL_LMR_START) {
|
||
CurrentState = (MRXSMB_STATE)
|
||
InterlockedCompareExchange(
|
||
(PLONG)&MRxSmbState,
|
||
MRXSMB_STARTED,
|
||
MRXSMB_START_IN_PROGRESS);
|
||
} else {
|
||
CurrentState = MRXSMB_START_IN_PROGRESS;
|
||
}
|
||
|
||
if (CurrentState == MRXSMB_START_IN_PROGRESS) {
|
||
MRxSmbPoRegistrationState = PoRegisterSystemState(
|
||
NULL,0);
|
||
|
||
// Initialize the SMB connection engine data structures
|
||
Status = SmbCeDbInit();
|
||
|
||
if (NT_SUCCESS(Status)) {
|
||
|
||
//
|
||
// If this is a normal start, initialize the security related data
|
||
// structures. If this is a remote boot start, we can't initialize
|
||
// security yet because user mode hasn't started yet.
|
||
//
|
||
|
||
if (RxContext->LowIoContext.ParamsFor.FsCtl.FsControlCode == FSCTL_LMR_START) {
|
||
Status = MRxSmbInitializeSecurity();
|
||
}
|
||
|
||
if (NT_SUCCESS(Status)) {
|
||
Status = SmbMrxInitializeStufferFacilities();
|
||
} else {
|
||
RxLogFailure (
|
||
MRxSmbDeviceObject,
|
||
NULL,
|
||
EVENT_RDR_UNEXPECTED_ERROR,
|
||
Status);
|
||
}
|
||
|
||
if (NT_SUCCESS(Status)) {
|
||
Status = MRxSmbInitializeRecurrentServices();
|
||
} else {
|
||
RxLogFailure (
|
||
MRxSmbDeviceObject,
|
||
NULL,
|
||
EVENT_RDR_UNEXPECTED_ERROR,
|
||
Status);
|
||
}
|
||
|
||
if (Status == STATUS_SUCCESS) {
|
||
if (Status != STATUS_SUCCESS) {
|
||
RxLogFailure (
|
||
MRxSmbDeviceObject,
|
||
NULL,
|
||
EVENT_RDR_UNEXPECTED_ERROR,
|
||
Status);
|
||
}
|
||
} else {
|
||
RxLogFailure (
|
||
MRxSmbDeviceObject,
|
||
NULL,
|
||
EVENT_RDR_UNEXPECTED_ERROR,
|
||
Status);
|
||
}
|
||
|
||
Status = SeRegisterLogonSessionTerminatedRoutine(
|
||
(PSE_LOGON_SESSION_TERMINATED_ROUTINE)
|
||
MRxSmbLogonSessionTerminationHandler);
|
||
}
|
||
} else if (MRxSmbState == MRXSMB_STARTED) {
|
||
Status = STATUS_REDIRECTOR_STARTED;
|
||
} else {
|
||
Status = STATUS_UNSUCCESSFUL;
|
||
}
|
||
|
||
return Status;
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
MRxSmbStop(
|
||
PRX_CONTEXT RxContext,
|
||
IN OUT PRDBSS_DEVICE_OBJECT RxDeviceObject
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is used to activate the mini redirector from the RDBSS perspective
|
||
|
||
Arguments:
|
||
|
||
RxContext - the context that was used to start the mini redirector
|
||
|
||
pContext - the SMB mini rdr context passed in at registration time.
|
||
|
||
Return Value:
|
||
|
||
RXSTATUS - The return status for the operation
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS Status;
|
||
|
||
PAGED_CODE();
|
||
|
||
PoUnregisterSystemState(
|
||
MRxSmbPoRegistrationState);
|
||
|
||
Status = MRxSmbUninitializeSecurity();
|
||
if (NT_SUCCESS(Status)) {
|
||
Status = SmbMrxFinalizeStufferFacilities();
|
||
}
|
||
|
||
ASSERT(NT_SUCCESS(Status));
|
||
|
||
SeUnregisterLogonSessionTerminatedRoutine(
|
||
(PSE_LOGON_SESSION_TERMINATED_ROUTINE)
|
||
MRxSmbLogonSessionTerminationHandler);
|
||
|
||
// tear down the recurrent services
|
||
MRxSmbTearDownRecurrentServices();
|
||
|
||
// Tear down the connection engine database
|
||
SmbCeDbTearDown();
|
||
|
||
// Tear down the registration for notifications
|
||
MRxSmbDeregisterForPnpNotifications();
|
||
|
||
// Wait for all the work items to be processed
|
||
RxSpinDownMRxDispatcher(MRxSmbDeviceObject);
|
||
|
||
// Deallocate the configuration strings ....
|
||
if (SmbCeContext.ComputerName.Buffer != NULL) {
|
||
RxFreePool(SmbCeContext.ComputerName.Buffer);
|
||
SmbCeContext.ComputerName.Buffer = NULL;
|
||
}
|
||
|
||
if (SmbCeContext.OperatingSystem.Buffer != NULL) {
|
||
RxFreePool(SmbCeContext.OperatingSystem.Buffer);
|
||
SmbCeContext.OperatingSystem.Buffer = NULL;
|
||
}
|
||
|
||
if (SmbCeContext.LanmanType.Buffer != NULL) {
|
||
RxFreePool(SmbCeContext.LanmanType.Buffer);
|
||
SmbCeContext.LanmanType.Buffer = NULL;
|
||
}
|
||
|
||
if (SmbCeContext.DomainName.Buffer != NULL) {
|
||
RxFreePool(SmbCeContext.DomainName.Buffer);
|
||
SmbCeContext.DomainName.Buffer = NULL;
|
||
}
|
||
|
||
if (SmbCeContext.Transports.Buffer != NULL) {
|
||
|
||
// the transports buffer is at the end of a larger buffer (by 12 bytes)
|
||
// allocated to read the value from the registry. recover the original buffer
|
||
// pointer in orer to free.
|
||
|
||
PKEY_VALUE_PARTIAL_INFORMATION TransportsValueFromRegistry;
|
||
TransportsValueFromRegistry = CONTAINING_RECORD(
|
||
SmbCeContext.Transports.Buffer,
|
||
KEY_VALUE_PARTIAL_INFORMATION,
|
||
Data[0]
|
||
);
|
||
//DbgPrint("b1 %08lx b2 %08lx\n", TransportsValueFromRegistry,SmbCeContext.Transports.Buffer);
|
||
RxFreePool(TransportsValueFromRegistry);
|
||
|
||
SmbCeContext.Transports.Buffer = NULL;
|
||
SmbCeContext.Transports.Length = 0;
|
||
SmbCeContext.Transports.MaximumLength = 0;
|
||
}
|
||
|
||
if (SmbCeContext.ServersWithExtendedSessTimeout.Buffer != NULL) {
|
||
|
||
// the transports buffer is at the end of a larger buffer (by 12 bytes)
|
||
// allocated to read the value from the registry. recover the original buffer
|
||
// pointer in orer to free.
|
||
|
||
PKEY_VALUE_PARTIAL_INFORMATION ServersValueFromRegistry;
|
||
ServersValueFromRegistry = CONTAINING_RECORD(
|
||
SmbCeContext.ServersWithExtendedSessTimeout.Buffer,
|
||
KEY_VALUE_PARTIAL_INFORMATION,
|
||
Data[0]
|
||
);
|
||
//DbgPrint("b1 %08lx b2 %08lx\n", TransportsValueFromRegistry,SmbCeContext.Transports.Buffer);
|
||
RxFreePool(ServersValueFromRegistry);
|
||
|
||
SmbCeContext.ServersWithExtendedSessTimeout.Buffer = NULL;
|
||
SmbCeContext.ServersWithExtendedSessTimeout.Length = 0;
|
||
SmbCeContext.ServersWithExtendedSessTimeout.MaximumLength = 0;
|
||
}
|
||
|
||
RtlFreeUnicodeString(&MRxSmbRemoteBootMachineName);
|
||
RtlFreeUnicodeString(&MRxSmbRemoteBootMachineDomain);
|
||
RtlFreeUnicodeString(&MRxSmbRemoteBootMachinePassword);
|
||
|
||
// MRxSmbUninitializeCSC();
|
||
|
||
if (s_pNegotiateSmb != NULL) {
|
||
RxFreePool(s_pNegotiateSmb - TRANSPORT_HEADER_SIZE);
|
||
s_pNegotiateSmb = NULL;
|
||
}
|
||
if (s_pNegotiateSmbRemoteBoot != NULL) {
|
||
RxFreePool(s_pNegotiateSmbRemoteBoot - TRANSPORT_HEADER_SIZE);
|
||
s_pNegotiateSmbRemoteBoot = NULL;
|
||
}
|
||
|
||
return(STATUS_SUCCESS);
|
||
}
|
||
|
||
NTSTATUS
|
||
MRxSmbInitializeSecurity (VOID)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine initializes the SMB miniredirector security .
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
Note:
|
||
|
||
This API can only be called from a FS process.
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS Status = STATUS_SUCCESS;
|
||
|
||
PAGED_CODE();
|
||
|
||
#ifndef WIN9X
|
||
// DbgBreakPoint();
|
||
if (MRxSmbSecurityInitialized)
|
||
return STATUS_SUCCESS;
|
||
|
||
if ( NULL == InitSecurityInterfaceW() ) {
|
||
ASSERT(FALSE);
|
||
Status = STATUS_INVALID_PARAMETER;
|
||
} else {
|
||
MRxSmbSecurityInitialized = TRUE;
|
||
Status = STATUS_SUCCESS;
|
||
}
|
||
#endif
|
||
|
||
ASSERT(IoGetCurrentProcess() == RxGetRDBSSProcess());
|
||
|
||
return Status;
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
MRxSmbUninitializeSecurity(VOID)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
Note:
|
||
|
||
This API can only be called from a FS process.
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS Status = STATUS_SUCCESS;
|
||
|
||
PAGED_CODE();
|
||
|
||
return Status;
|
||
}
|
||
|
||
//
|
||
// Remote boot needs to use the ComputerName value, not ActiveComputerName, because
|
||
// ActiveComputerName is volatile and is set relatively late in system initialization.
|
||
//
|
||
|
||
#define SMBMRX_CONFIG_COMPUTER_NAME \
|
||
L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\ComputerName\\ActiveComputerName"
|
||
#define SMBMRX_CONFIG_COMPUTER_NAME_NONVOLATILE \
|
||
L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\ComputerName\\ComputerName"
|
||
|
||
#define COMPUTERNAME L"ComputerName"
|
||
|
||
#define SMBMRX_CONFIG_TRANSPORTS \
|
||
L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\LanmanWorkStation\\Linkage"
|
||
|
||
#define TRANSPORT_BINDINGS L"Bind"
|
||
|
||
#define SMB_SERVER_PARAMETERS \
|
||
L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\LanManServer\\Parameters"
|
||
|
||
BOOL
|
||
IsTerminalServicesServer()
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine determines whether this is a TS machine, and that we should enable
|
||
the per-user connectivity for multiplexing
|
||
|
||
Arguments:
|
||
|
||
None
|
||
|
||
Return Value:
|
||
|
||
TRUE for machines that are SERVER or better, and are running non-single-user TS.
|
||
FALSE for all others.
|
||
|
||
--*/
|
||
|
||
{
|
||
RTL_OSVERSIONINFOEXW Osvi;
|
||
DWORD TypeMask;
|
||
DWORDLONG ConditionMask;
|
||
|
||
// First make sure that its a TS machine
|
||
memset(&Osvi, 0, sizeof(OSVERSIONINFOEX));
|
||
Osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
|
||
Osvi.wSuiteMask = VER_SUITE_TERMINAL;
|
||
TypeMask = VER_SUITENAME;
|
||
ConditionMask = 0;
|
||
VER_SET_CONDITION(ConditionMask, VER_SUITENAME, VER_AND);
|
||
if( NT_SUCCESS(RtlVerifyVersionInfo(&Osvi, TypeMask, ConditionMask)) )
|
||
{
|
||
// Now make sure this isn't single-user TS
|
||
Osvi.wSuiteMask = VER_SUITE_SINGLEUSERTS;
|
||
TypeMask = VER_SUITENAME;
|
||
ConditionMask = 0;
|
||
VER_SET_CONDITION(ConditionMask, VER_SUITENAME, VER_AND);
|
||
return !NT_SUCCESS(RtlVerifyVersionInfo(&Osvi, TypeMask, ConditionMask));
|
||
}
|
||
else
|
||
{
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
VOID
|
||
MRxSmbReadMiscellaneousRegistryParameters()
|
||
{
|
||
NTSTATUS Status;
|
||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||
UNICODE_STRING UnicodeString;
|
||
UNICODE_STRING WorkStationParametersRegistryKeyName;
|
||
HANDLE ParametersHandle;
|
||
ULONG Temp;
|
||
KEY_VALUE_PARTIAL_INFORMATION InitialPartialInformationValue;
|
||
#if defined(REMOTE_BOOT)
|
||
PKEY_VALUE_PARTIAL_INFORMATION RbrListFromRegistry;
|
||
ULONG AllocationLength;
|
||
PWCHAR RbrList;
|
||
PWCHAR redirectionEntry;
|
||
UNICODE_STRING prefix;
|
||
PRBR_PREFIX prefixEntry;
|
||
ULONG prefixEntryLength;
|
||
|
||
PWCHAR DefaultRbrList =
|
||
L"L\\pagefile.sys\0"
|
||
L"L\\temp\0"
|
||
L"L\\tmp\0"
|
||
L"R\\\0"
|
||
;
|
||
#endif // defined(REMOTE_BOOT)
|
||
|
||
PAGED_CODE();
|
||
|
||
RtlInitUnicodeString(&UnicodeString, SMBMRX_MINIRDR_PARAMETERS);
|
||
|
||
InitializeObjectAttributes(
|
||
&ObjectAttributes,
|
||
&UnicodeString,
|
||
OBJ_CASE_INSENSITIVE,
|
||
NULL,
|
||
NULL
|
||
);
|
||
|
||
Status = ZwOpenKey (&ParametersHandle, KEY_READ, &ObjectAttributes);
|
||
|
||
if (NT_SUCCESS(Status)) {
|
||
if (0) {
|
||
MRxSmbGetUlongRegistryParameter(
|
||
ParametersHandle,
|
||
L"NoPreciousServerSetup",
|
||
(PULONG)&Temp,
|
||
FALSE
|
||
);
|
||
}
|
||
|
||
Status = MRxSmbGetUlongRegistryParameter(
|
||
ParametersHandle,
|
||
L"DeferredOpensEnabled",
|
||
(PULONG)&Temp,
|
||
FALSE );
|
||
|
||
if (NT_SUCCESS(Status))
|
||
MRxSmbDeferredOpensEnabled = (BOOLEAN)Temp;
|
||
|
||
Status = MRxSmbGetUlongRegistryParameter(
|
||
ParametersHandle,
|
||
L"OplocksDisabled",
|
||
(PULONG)&Temp,
|
||
FALSE );
|
||
|
||
if (NT_SUCCESS(Status))
|
||
MRxSmbOplocksDisabled = (BOOLEAN)Temp;
|
||
|
||
|
||
MRxSmbIsCscEnabled = TRUE;
|
||
|
||
//this should be a macro......
|
||
Status = MRxSmbGetUlongRegistryParameter(
|
||
ParametersHandle,
|
||
L"CscEnabled",
|
||
(PULONG)&Temp,
|
||
FALSE );
|
||
|
||
if (NT_SUCCESS(Status)) {
|
||
MRxSmbIsCscEnabled = (BOOLEAN)Temp;
|
||
}
|
||
|
||
|
||
//this would be the end of the macro.......
|
||
|
||
if (MRxSmbIsCscEnabled) {
|
||
|
||
//this should be a macro......
|
||
Status = MRxSmbGetUlongRegistryParameter(
|
||
ParametersHandle,
|
||
L"CscEnabledDCON",
|
||
(PULONG)&Temp,
|
||
FALSE );
|
||
|
||
if (NT_SUCCESS(Status))
|
||
MRxSmbIsCscEnabledForDisconnected = (BOOLEAN)Temp;
|
||
//this would be the end of the macro.......
|
||
|
||
|
||
Status = MRxSmbGetUlongRegistryParameter(
|
||
ParametersHandle,
|
||
L"CscEnableTransitionByDefault",
|
||
(PULONG)&Temp,
|
||
FALSE );
|
||
|
||
if (NT_SUCCESS(Status))
|
||
MRxSmbCscTransitionEnabledByDefault = (BOOLEAN)Temp;
|
||
|
||
Status = MRxSmbGetUlongRegistryParameter(
|
||
ParametersHandle,
|
||
L"CscEnableAutoDial",
|
||
(PULONG)&Temp,
|
||
FALSE );
|
||
|
||
if (NT_SUCCESS(Status))
|
||
MRxSmbCscAutoDialEnabled = (BOOLEAN)Temp;
|
||
|
||
|
||
} else {
|
||
|
||
MRxSmbIsCscEnabledForDisconnected = FALSE;
|
||
|
||
}
|
||
|
||
Status = MRxSmbGetUlongRegistryParameter(
|
||
ParametersHandle,
|
||
L"EnableCompression",
|
||
(PULONG)&Temp,
|
||
FALSE);
|
||
|
||
if (NT_SUCCESS(Status) &&
|
||
(Temp != 0)) {
|
||
MRxSmbEnableCompression = TRUE;
|
||
}
|
||
|
||
Status = MRxSmbGetUlongRegistryParameter(
|
||
ParametersHandle,
|
||
L"IgnoreBindingOrder",
|
||
(PULONG)&Temp,
|
||
FALSE);
|
||
|
||
if (NT_SUCCESS(Status)) {
|
||
MRxSmbObeyBindingOrder = !((BOOLEAN)Temp);
|
||
}
|
||
|
||
#if defined(REMOTE_BOOT)
|
||
RbrList = DefaultRbrList;
|
||
|
||
RtlInitUnicodeString(&UnicodeString, L"RemoteBootRedirectionList");
|
||
Status = ZwQueryValueKey(
|
||
ParametersHandle,
|
||
&UnicodeString,
|
||
KeyValuePartialInformation,
|
||
&InitialPartialInformationValue,
|
||
sizeof(InitialPartialInformationValue),
|
||
&Temp);
|
||
if (Status== STATUS_BUFFER_OVERFLOW) {
|
||
Status = STATUS_SUCCESS;
|
||
}
|
||
if (NT_SUCCESS(Status)) {
|
||
|
||
AllocationLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION)
|
||
+ InitialPartialInformationValue.DataLength;
|
||
|
||
RbrListFromRegistry = RxAllocatePoolWithTag(
|
||
PagedPool,
|
||
AllocationLength,
|
||
MRXSMB_MISC_POOLTAG);
|
||
if (RbrListFromRegistry != NULL) {
|
||
|
||
Status = ZwQueryValueKey(
|
||
ParametersHandle,
|
||
&UnicodeString,
|
||
KeyValuePartialInformation,
|
||
RbrListFromRegistry,
|
||
AllocationLength,
|
||
&Temp);
|
||
|
||
if (NT_SUCCESS(Status) &&
|
||
(RbrListFromRegistry->DataLength > 0) &&
|
||
(RbrListFromRegistry->Type == REG_MULTI_SZ)) {
|
||
RbrList = (PWCHAR)(&RbrListFromRegistry->Data[0]);
|
||
}
|
||
}
|
||
}
|
||
|
||
RtlInitializeUnicodePrefix( &MRxSmbRemoteBootRedirectionTable );
|
||
|
||
for ( redirectionEntry = RbrList; *redirectionEntry != 0; ) {
|
||
|
||
BOOLEAN redirect;
|
||
|
||
if ( *redirectionEntry == L'L' ) {
|
||
redirect = TRUE;
|
||
redirectionEntry++;
|
||
} else if ( *redirectionEntry == L'R' ) {
|
||
redirect = FALSE;
|
||
redirectionEntry++;
|
||
} else {
|
||
redirect = TRUE;
|
||
}
|
||
|
||
RtlInitUnicodeString( &prefix, redirectionEntry );
|
||
redirectionEntry = (PWCHAR)((PCHAR)redirectionEntry + prefix.MaximumLength);
|
||
|
||
prefixEntryLength = sizeof(RBR_PREFIX) + prefix.MaximumLength;
|
||
prefixEntry = RxAllocatePoolWithTag(
|
||
PagedPool,
|
||
prefixEntryLength,
|
||
MRXSMB_MISC_POOLTAG
|
||
);
|
||
|
||
|
||
if ( prefixEntry != NULL ) {
|
||
prefixEntry->Redirect = redirect;
|
||
prefixEntry->Prefix.Buffer = (PWCH)(prefixEntry + 1);
|
||
prefixEntry->Prefix.MaximumLength = prefix.Length + sizeof(WCHAR);
|
||
RtlCopyUnicodeString( &prefixEntry->Prefix, &prefix );
|
||
|
||
if ( !RtlInsertUnicodePrefix(
|
||
&MRxSmbRemoteBootRedirectionTable,
|
||
&prefixEntry->Prefix,
|
||
&prefixEntry->TableEntry
|
||
) ) {
|
||
|
||
//
|
||
// The prefix is already in the table. Ignore the duplicate.
|
||
//
|
||
|
||
RxFreePool( prefixEntry );
|
||
}
|
||
}
|
||
}
|
||
#endif // defined(REMOTE_BOOT)
|
||
|
||
ZwClose(ParametersHandle);
|
||
}
|
||
|
||
// For server terminal services machines, we multiplex based on LUID.
|
||
if( IsTerminalServicesServer() && !MRxSmbIsCscEnabled )
|
||
{
|
||
MRxSmbConnectionIdLevel = 2;
|
||
}
|
||
|
||
RtlInitUnicodeString(&WorkStationParametersRegistryKeyName, SMBMRX_WORKSTATION_PARAMETERS);
|
||
|
||
InitializeObjectAttributes(
|
||
&ObjectAttributes,
|
||
&WorkStationParametersRegistryKeyName,
|
||
OBJ_CASE_INSENSITIVE,
|
||
NULL,
|
||
NULL
|
||
);
|
||
|
||
Status = ZwOpenKey(&ParametersHandle, KEY_READ, &ObjectAttributes);
|
||
|
||
if (NT_SUCCESS(Status)) {
|
||
Status = MRxSmbGetUlongRegistryParameter(
|
||
ParametersHandle,
|
||
L"RequireSecuritySignature",
|
||
(PULONG)&Temp,
|
||
FALSE);
|
||
|
||
if (NT_SUCCESS(Status) && (Temp != 0)) {
|
||
MRxSmbSecuritySignaturesEnabled = TRUE;
|
||
MRxSmbSecuritySignaturesRequired = TRUE;
|
||
} else {
|
||
Status = MRxSmbGetUlongRegistryParameter(
|
||
ParametersHandle,
|
||
L"EnableSecuritySignature",
|
||
(PULONG)&Temp,
|
||
FALSE);
|
||
|
||
if( NT_SUCCESS(Status) )
|
||
{
|
||
if( Temp != 0 )
|
||
{
|
||
MRxSmbSecuritySignaturesEnabled = TRUE;
|
||
}
|
||
else
|
||
{
|
||
MRxSmbSecuritySignaturesEnabled = FALSE;
|
||
}
|
||
}
|
||
}
|
||
|
||
Status = MRxSmbGetUlongRegistryParameter(
|
||
ParametersHandle,
|
||
L"EnablePlainTextPassword",
|
||
(PULONG)&Temp,
|
||
FALSE );
|
||
|
||
if (NT_SUCCESS(Status))
|
||
EnablePlainTextPassword = (BOOLEAN)Temp;
|
||
|
||
Status = MRxSmbGetUlongRegistryParameter(
|
||
ParametersHandle,
|
||
L"OffLineFileTimeoutIntervalInSeconds",
|
||
(PULONG)&Temp,
|
||
FALSE );
|
||
|
||
if (NT_SUCCESS(Status))
|
||
OffLineFileTimeoutInterval = (ULONG)Temp;
|
||
|
||
Status = MRxSmbGetUlongRegistryParameter(
|
||
ParametersHandle,
|
||
L"ExtendedSessTimeout",
|
||
(PULONG)&Temp,
|
||
FALSE );
|
||
|
||
if (NT_SUCCESS(Status))
|
||
ExtendedSessTimeoutInterval = (ULONG)Temp;
|
||
|
||
Status = MRxSmbGetUlongRegistryParameter(
|
||
ParametersHandle,
|
||
L"MaxNumOfExchangesForPipelineReadWrite",
|
||
(PULONG)&Temp,
|
||
FALSE );
|
||
|
||
if (NT_SUCCESS(Status))
|
||
MaxNumOfExchangesForPipelineReadWrite = (ULONG)Temp;
|
||
|
||
Status = MRxSmbGetUlongRegistryParameter(
|
||
ParametersHandle,
|
||
L"Win9xSessionRestriction",
|
||
(PULONG)&Temp,
|
||
FALSE );
|
||
|
||
if (NT_SUCCESS(Status))
|
||
Win9xSessionRestriction = (BOOLEAN)Temp;
|
||
|
||
Status = MRxSmbGetUlongRegistryParameter(
|
||
ParametersHandle,
|
||
L"EnableCachingOnWriteOnlyOpens",
|
||
(PULONG)&Temp,
|
||
FALSE );
|
||
|
||
if (NT_SUCCESS(Status))
|
||
MRxSmbEnableCachingOnWriteOnlyOpens = (BOOLEAN)Temp;
|
||
|
||
Status = MRxSmbGetUlongRegistryParameter(
|
||
ParametersHandle,
|
||
L"DisableByteRangeLockingOnReadOnlyFiles",
|
||
(PULONG)&Temp,
|
||
FALSE );
|
||
|
||
if (NT_SUCCESS(Status))
|
||
DisableByteRangeLockingOnReadOnlyFiles = (BOOLEAN)Temp;
|
||
|
||
Status = MRxSmbGetUlongRegistryParameter(
|
||
ParametersHandle,
|
||
L"UniqueFileNames",
|
||
(PULONG)&Temp,
|
||
FALSE );
|
||
|
||
if (NT_SUCCESS(Status))
|
||
UniqueFileNames = (BOOLEAN)Temp;
|
||
|
||
//
|
||
// Modified LOGOFF behavior for downlevel servers.
|
||
//
|
||
MRxSmbEnableDownLevelLogOff = FALSE;
|
||
Status = MRxSmbGetUlongRegistryParameter(
|
||
ParametersHandle,
|
||
L"EnableDownLevelLogOff",
|
||
(PULONG)&Temp,
|
||
FALSE);
|
||
|
||
if ( NT_SUCCESS( Status ) ) {
|
||
if( Temp != 0 )
|
||
{
|
||
MRxSmbEnableDownLevelLogOff = TRUE;
|
||
}
|
||
}
|
||
|
||
|
||
ZwClose(ParametersHandle);
|
||
}
|
||
|
||
// Detect if system setup in progress
|
||
RtlInitUnicodeString(&WorkStationParametersRegistryKeyName, SYSTEM_SETUP_PARAMETERS);
|
||
|
||
InitializeObjectAttributes(
|
||
&ObjectAttributes,
|
||
&WorkStationParametersRegistryKeyName,
|
||
OBJ_CASE_INSENSITIVE,
|
||
NULL,
|
||
NULL
|
||
);
|
||
|
||
Status = ZwOpenKey(&ParametersHandle, KEY_READ, &ObjectAttributes);
|
||
|
||
if (NT_SUCCESS(Status)) {
|
||
Status = MRxSmbGetUlongRegistryParameter(
|
||
ParametersHandle,
|
||
L"SystemSetupInProgress",
|
||
(PULONG)&Temp,
|
||
FALSE );
|
||
|
||
if (NT_SUCCESS(Status))
|
||
SetupInProgress = (BOOLEAN)Temp;
|
||
|
||
ZwClose(ParametersHandle);
|
||
}
|
||
|
||
// initialize event log parameter so that it can translate dos error into text description
|
||
RtlInitUnicodeString(&WorkStationParametersRegistryKeyName, EVENTLOG_MRXSMB_PARAMETERS);
|
||
|
||
InitializeObjectAttributes(
|
||
&ObjectAttributes,
|
||
&WorkStationParametersRegistryKeyName,
|
||
OBJ_CASE_INSENSITIVE,
|
||
NULL,
|
||
NULL
|
||
);
|
||
|
||
Status = ZwOpenKey(&ParametersHandle, KEY_READ, &ObjectAttributes);
|
||
|
||
if (NT_SUCCESS(Status)) {
|
||
ULONG Storage[16];
|
||
PKEY_VALUE_PARTIAL_INFORMATION Value;
|
||
ULONG ValueSize;
|
||
NTSTATUS Status;
|
||
ULONG BytesRead;
|
||
|
||
RtlInitUnicodeString(&UnicodeString, L"ParameterMessageFile");
|
||
Value = (PKEY_VALUE_PARTIAL_INFORMATION)Storage;
|
||
ValueSize = sizeof(Storage);
|
||
|
||
Status = ZwQueryValueKey(
|
||
ParametersHandle,
|
||
&UnicodeString,
|
||
KeyValuePartialInformation,
|
||
Value,
|
||
ValueSize,
|
||
&BytesRead);
|
||
|
||
if (Status != STATUS_SUCCESS || Value->Type != REG_EXPAND_SZ) {
|
||
UNICODE_STRING UnicodeString1;
|
||
|
||
RtlInitUnicodeString(&UnicodeString1, L"%SystemRoot%\\System32\\kernel32.dll");
|
||
|
||
Status = ZwSetValueKey(
|
||
ParametersHandle,
|
||
&UnicodeString,
|
||
0,
|
||
REG_EXPAND_SZ,
|
||
UnicodeString1.Buffer,
|
||
UnicodeString1.Length+sizeof(NULL));
|
||
}
|
||
|
||
ZwClose(ParametersHandle);
|
||
}
|
||
|
||
//
|
||
// Get Server GUID for Loopback Detection
|
||
// Server Restart updates cached GUID ????
|
||
//
|
||
RtlInitUnicodeString( &UnicodeString, SMB_SERVER_PARAMETERS );
|
||
|
||
InitializeObjectAttributes(
|
||
&ObjectAttributes,
|
||
&UnicodeString,
|
||
OBJ_CASE_INSENSITIVE,
|
||
NULL,
|
||
NULL
|
||
);
|
||
|
||
Status = ZwOpenKey( &ParametersHandle, KEY_READ, &ObjectAttributes );
|
||
|
||
if( NT_SUCCESS( Status ) ) {
|
||
|
||
ULONG BytesRead;
|
||
ULONG regValue[ sizeof( KEY_VALUE_PARTIAL_INFORMATION ) + sizeof( GUID ) ];
|
||
ULONG regValueSize = sizeof( regValue );
|
||
|
||
|
||
RtlInitUnicodeString( &UnicodeString, L"Guid" );
|
||
Status = ZwQueryValueKey( ParametersHandle,
|
||
&UnicodeString,
|
||
KeyValuePartialInformation,
|
||
(PKEY_VALUE_PARTIAL_INFORMATION)®Value,
|
||
regValueSize,
|
||
&BytesRead
|
||
);
|
||
|
||
RtlCopyMemory(&CachedServerGuid,
|
||
((PKEY_VALUE_PARTIAL_INFORMATION)®Value)->Data,
|
||
sizeof(GUID));
|
||
|
||
|
||
ZwClose(ParametersHandle);
|
||
}
|
||
}
|
||
|
||
NTSTATUS
|
||
SmbCeGetConfigurationInformation()
|
||
{
|
||
ULONG Storage[256];
|
||
UNICODE_STRING UnicodeString;
|
||
HANDLE hRegistryKey;
|
||
NTSTATUS Status;
|
||
ULONG BytesRead;
|
||
|
||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||
PKEY_VALUE_FULL_INFORMATION Value = (PKEY_VALUE_FULL_INFORMATION)Storage;
|
||
KEY_VALUE_PARTIAL_INFORMATION InitialPartialInformationValue;
|
||
ULONG AllocationLength;
|
||
PKEY_VALUE_PARTIAL_INFORMATION TransportsValueFromRegistry;
|
||
|
||
PAGED_CODE();
|
||
|
||
IF_NOT_MRXSMB_CSC_ENABLED {
|
||
MRxSmbReadMiscellaneousRegistryParameters();
|
||
}
|
||
|
||
// Obtain the list of transports associated with SMB redirector. This is stored
|
||
// as a multivalued string and is used subsequently to weed out the
|
||
// appropriate transports. This is a two step process; first we try to find out
|
||
// how much space we need; then we allocate; then we read in. unfortunately, the kind of
|
||
// structure that we have to use to get the value has a header on it, so we have to offset the
|
||
// returned pointer both here and in the free routine.
|
||
|
||
//CODE.IMPROVEMENT we should perhaps get a subroutine going that does all this
|
||
//also, there are no log entries.
|
||
//also, we should be doing partial_infos instead of full
|
||
|
||
RtlInitUnicodeString(&UnicodeString, SMBMRX_CONFIG_TRANSPORTS);
|
||
|
||
InitializeObjectAttributes(
|
||
&ObjectAttributes,
|
||
&UnicodeString, // name
|
||
OBJ_CASE_INSENSITIVE, // attributes
|
||
NULL, // root
|
||
NULL); // security descriptor
|
||
|
||
Status = ZwOpenKey (&hRegistryKey, KEY_READ, &ObjectAttributes);
|
||
if (!NT_SUCCESS(Status)) {
|
||
return Status;
|
||
}
|
||
|
||
RtlInitUnicodeString(&UnicodeString, TRANSPORT_BINDINGS);
|
||
Status = ZwQueryValueKey(
|
||
hRegistryKey,
|
||
&UnicodeString,
|
||
KeyValuePartialInformation,
|
||
&InitialPartialInformationValue,
|
||
sizeof(InitialPartialInformationValue),
|
||
&BytesRead);
|
||
if (Status== STATUS_BUFFER_OVERFLOW) {
|
||
Status = STATUS_SUCCESS;
|
||
}
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
ZwClose(hRegistryKey);
|
||
return Status;
|
||
}
|
||
|
||
AllocationLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION)
|
||
+ InitialPartialInformationValue.DataLength;
|
||
if (0) {
|
||
DbgPrint("SizeofBindingInfo=%08lx %08lx\n",
|
||
AllocationLength,
|
||
InitialPartialInformationValue.DataLength);
|
||
}
|
||
|
||
if (SmbCeContext.Transports.Buffer != NULL) {
|
||
|
||
// the transports buffer is at the end of a larger buffer (by 12 bytes)
|
||
// allocated to read the value from the registry. recover the original buffer
|
||
// pointer in orer to free.
|
||
|
||
TransportsValueFromRegistry = CONTAINING_RECORD(
|
||
SmbCeContext.Transports.Buffer,
|
||
KEY_VALUE_PARTIAL_INFORMATION,
|
||
Data[0]
|
||
);
|
||
//DbgPrint("b1 %08lx b2 %08lx\n", TransportsValueFromRegistry,SmbCeContext.Transports.Buffer);
|
||
RxFreePool(TransportsValueFromRegistry);
|
||
|
||
SmbCeContext.Transports.Buffer = NULL;
|
||
SmbCeContext.Transports.Length = 0;
|
||
SmbCeContext.Transports.MaximumLength = 0;
|
||
}
|
||
|
||
(PBYTE)TransportsValueFromRegistry = RxAllocatePoolWithTag(
|
||
PagedPool,
|
||
AllocationLength,
|
||
MRXSMB_MISC_POOLTAG);
|
||
|
||
if (TransportsValueFromRegistry == NULL) {
|
||
ZwClose(hRegistryKey);
|
||
return(STATUS_INSUFFICIENT_RESOURCES);
|
||
}
|
||
|
||
Status = ZwQueryValueKey(
|
||
hRegistryKey,
|
||
&UnicodeString,
|
||
KeyValuePartialInformation,
|
||
TransportsValueFromRegistry,
|
||
AllocationLength,
|
||
&BytesRead);
|
||
|
||
if (NT_SUCCESS(Status) &&
|
||
(TransportsValueFromRegistry->DataLength > 0) &&
|
||
(TransportsValueFromRegistry->Type == REG_MULTI_SZ)) {
|
||
|
||
SmbCeContext.Transports.MaximumLength =
|
||
SmbCeContext.Transports.Length = (USHORT)TransportsValueFromRegistry->DataLength;
|
||
SmbCeContext.Transports.Buffer = (PWCHAR)(&TransportsValueFromRegistry->Data[0]);
|
||
//DbgPrint("b1 %08lx b2 %08lx\n", TransportsValueFromRegistry,SmbCeContext.Transports.Buffer);
|
||
} else {
|
||
RxLog(("Invalid Transport Binding string... using all transports"));
|
||
SmbLog(LOG,
|
||
SmbCeGetConfigurationInformation,
|
||
LOGULONG(Status));
|
||
RxFreePool(TransportsValueFromRegistry);
|
||
TransportsValueFromRegistry = NULL;
|
||
}
|
||
|
||
ZwClose(hRegistryKey);
|
||
|
||
return Status;
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
SmbCeGetComputerName(
|
||
VOID
|
||
)
|
||
{
|
||
ULONG Storage[256];
|
||
UNICODE_STRING UnicodeString;
|
||
HANDLE hRegistryKey;
|
||
NTSTATUS Status;
|
||
ULONG BytesRead;
|
||
|
||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||
PKEY_VALUE_FULL_INFORMATION Value = (PKEY_VALUE_FULL_INFORMATION)Storage;
|
||
KEY_VALUE_PARTIAL_INFORMATION InitialPartialInformationValue;
|
||
ULONG AllocationLength;
|
||
|
||
PAGED_CODE();
|
||
|
||
ASSERT(SmbCeContext.ComputerName.Buffer == NULL);
|
||
|
||
// Obtain the computer name. This is used in formulating the local NETBIOS address
|
||
RtlInitUnicodeString(&SmbCeContext.ComputerName, NULL);
|
||
if (!MRxSmbBootedRemotely) {
|
||
RtlInitUnicodeString(&UnicodeString, SMBMRX_CONFIG_COMPUTER_NAME);
|
||
} else {
|
||
//
|
||
// For remote boot, we are initializing long before the volatile
|
||
// ActiveComputerNameKey is created, so we need to read from the
|
||
// nonvolatile key instead. This is not a problem, because we know
|
||
// that the computer name hasn't been changed since the computer was
|
||
// booted -- since we're very early in the boot sequence -- so the
|
||
// nonvolatile key has the correct computer name.
|
||
//
|
||
RtlInitUnicodeString(&UnicodeString, SMBMRX_CONFIG_COMPUTER_NAME_NONVOLATILE);
|
||
}
|
||
|
||
InitializeObjectAttributes(
|
||
&ObjectAttributes,
|
||
&UnicodeString, // name
|
||
OBJ_CASE_INSENSITIVE, // attributes
|
||
NULL, // root
|
||
NULL); // security descriptor
|
||
|
||
Status = ZwOpenKey (&hRegistryKey, KEY_READ, &ObjectAttributes);
|
||
if (!NT_SUCCESS(Status)) {
|
||
return Status;
|
||
}
|
||
|
||
RtlInitUnicodeString(&UnicodeString, COMPUTERNAME);
|
||
Status = ZwQueryValueKey(
|
||
hRegistryKey,
|
||
&UnicodeString,
|
||
KeyValueFullInformation,
|
||
Value,
|
||
sizeof(Storage),
|
||
&BytesRead);
|
||
|
||
if (NT_SUCCESS(Status)) {
|
||
// Rtl conversion routines require NULL char to be excluded from the
|
||
// length.
|
||
SmbCeContext.ComputerName.MaximumLength =
|
||
SmbCeContext.ComputerName.Length = (USHORT)Value->DataLength - sizeof(WCHAR);
|
||
|
||
SmbCeContext.ComputerName.Buffer = RxAllocatePoolWithTag(
|
||
PagedPool,
|
||
SmbCeContext.ComputerName.Length,
|
||
MRXSMB_MISC_POOLTAG);
|
||
|
||
if (SmbCeContext.ComputerName.Buffer != NULL) {
|
||
RtlCopyMemory(SmbCeContext.ComputerName.Buffer,
|
||
(PCHAR)Value+Value->DataOffset,
|
||
Value->DataLength - sizeof(WCHAR));
|
||
} else {
|
||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
}
|
||
|
||
ZwClose(hRegistryKey);
|
||
|
||
return Status;
|
||
}
|
||
|
||
NTSTATUS
|
||
SmbCeGetOperatingSystemInformation(
|
||
VOID
|
||
)
|
||
{
|
||
ULONG Storage[256], Storage2[256];
|
||
UNICODE_STRING UnicodeString;
|
||
HANDLE hRegistryKey;
|
||
NTSTATUS Status, Status2;
|
||
ULONG BytesRead;
|
||
|
||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||
PKEY_VALUE_FULL_INFORMATION Value = (PKEY_VALUE_FULL_INFORMATION)Storage;
|
||
PKEY_VALUE_FULL_INFORMATION Value2 = (PKEY_VALUE_FULL_INFORMATION)Storage2;
|
||
KEY_VALUE_PARTIAL_INFORMATION InitialPartialInformationValue;
|
||
ULONG AllocationLength;
|
||
|
||
PAGED_CODE();
|
||
|
||
ASSERT(SmbCeContext.OperatingSystem.Buffer == NULL);
|
||
ASSERT(SmbCeContext.LanmanType.Buffer == NULL);
|
||
|
||
RtlInitUnicodeString(&UnicodeString, RDR_CONFIG_CURRENT_WINDOWS_VERSION);
|
||
|
||
InitializeObjectAttributes(
|
||
&ObjectAttributes,
|
||
&UnicodeString, // name
|
||
OBJ_CASE_INSENSITIVE, // attributes
|
||
NULL, // root
|
||
NULL); // security descriptor
|
||
|
||
Status = ZwOpenKey (&hRegistryKey, KEY_READ, &ObjectAttributes);
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
return Status;
|
||
}
|
||
|
||
RtlInitUnicodeString(&UnicodeString, RDR_CONFIG_OPERATING_SYSTEM);
|
||
Status = ZwQueryValueKey(
|
||
hRegistryKey,
|
||
&UnicodeString,
|
||
KeyValueFullInformation,
|
||
Value,
|
||
sizeof(Storage),
|
||
&BytesRead);
|
||
|
||
if (NT_SUCCESS(Status)) {
|
||
|
||
// check for existance of Service Pack String
|
||
RtlInitUnicodeString(&UnicodeString, L"CSDVersion");
|
||
Status2 = ZwQueryValueKey(
|
||
hRegistryKey,
|
||
&UnicodeString,
|
||
KeyValueFullInformation,
|
||
Value2,
|
||
sizeof(Storage2),
|
||
&BytesRead);
|
||
|
||
SmbCeContext.OperatingSystem.MaximumLength =
|
||
(USHORT)Value->DataLength + sizeof(RDR_CONFIG_OPERATING_SYSTEM_NAME) - sizeof(WCHAR);
|
||
|
||
if(NT_SUCCESS(Status2)) {
|
||
SmbCeContext.OperatingSystem.MaximumLength += (USHORT)Value2->DataLength;
|
||
}
|
||
|
||
SmbCeContext.OperatingSystem.Length = SmbCeContext.OperatingSystem.MaximumLength - sizeof(WCHAR);
|
||
|
||
SmbCeContext.OperatingSystem.Buffer = RxAllocatePoolWithTag(
|
||
PagedPool,
|
||
SmbCeContext.OperatingSystem.MaximumLength,
|
||
MRXSMB_MISC_POOLTAG);
|
||
|
||
if (SmbCeContext.OperatingSystem.Buffer != NULL) {
|
||
RtlCopyMemory(SmbCeContext.OperatingSystem.Buffer,
|
||
RDR_CONFIG_OPERATING_SYSTEM_NAME,
|
||
sizeof(RDR_CONFIG_OPERATING_SYSTEM_NAME));
|
||
|
||
RtlCopyMemory((SmbCeContext.OperatingSystem.Buffer +
|
||
(sizeof(RDR_CONFIG_OPERATING_SYSTEM_NAME)/sizeof(WCHAR)) - 1),
|
||
(PCHAR)Value+Value->DataOffset,
|
||
Value->DataLength);
|
||
|
||
if(NT_SUCCESS(Status2)) {
|
||
|
||
// add a space
|
||
RtlCopyMemory(SmbCeContext.OperatingSystem.Buffer +
|
||
(sizeof(RDR_CONFIG_OPERATING_SYSTEM_NAME) + Value->DataLength)/sizeof(WCHAR) - 2,
|
||
L" ",
|
||
sizeof(WCHAR));
|
||
|
||
RtlCopyMemory(SmbCeContext.OperatingSystem.Buffer +
|
||
(sizeof(RDR_CONFIG_OPERATING_SYSTEM_NAME) + Value->DataLength)/sizeof(WCHAR) - 1,
|
||
(PCHAR)Value2+Value2->DataOffset,
|
||
Value2->DataLength);
|
||
}
|
||
|
||
} else {
|
||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
}
|
||
|
||
if (NT_SUCCESS(Status)) {
|
||
RtlInitUnicodeString(&UnicodeString, RDR_CONFIG_OPERATING_SYSTEM_VERSION);
|
||
Status = ZwQueryValueKey(
|
||
hRegistryKey,
|
||
&UnicodeString,
|
||
KeyValueFullInformation,
|
||
Value,
|
||
sizeof(Storage),
|
||
&BytesRead);
|
||
|
||
if (NT_SUCCESS(Status)) {
|
||
SmbCeContext.LanmanType.MaximumLength =
|
||
SmbCeContext.LanmanType.Length = (USHORT)Value->DataLength +
|
||
sizeof(RDR_CONFIG_OPERATING_SYSTEM_NAME) -
|
||
sizeof(WCHAR);
|
||
|
||
SmbCeContext.LanmanType.Buffer = RxAllocatePoolWithTag(
|
||
PagedPool,
|
||
SmbCeContext.LanmanType.Length,
|
||
MRXSMB_MISC_POOLTAG);
|
||
if (SmbCeContext.LanmanType.Buffer != NULL) {
|
||
RtlCopyMemory(
|
||
SmbCeContext.LanmanType.Buffer,
|
||
RDR_CONFIG_OPERATING_SYSTEM_NAME,
|
||
sizeof(RDR_CONFIG_OPERATING_SYSTEM_NAME));
|
||
|
||
RtlCopyMemory(
|
||
(SmbCeContext.LanmanType.Buffer +
|
||
(sizeof(RDR_CONFIG_OPERATING_SYSTEM_NAME)/sizeof(WCHAR)) - 1),
|
||
(PCHAR)Value+Value->DataOffset,
|
||
Value->DataLength);
|
||
} else {
|
||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
}
|
||
}
|
||
|
||
ZwClose(hRegistryKey);
|
||
|
||
return Status;
|
||
}
|
||
|
||
NTSTATUS
|
||
MRxSmbPnpIrpCompletion(
|
||
PDEVICE_OBJECT pDeviceObject,
|
||
PIRP pIrp,
|
||
PVOID pContext)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine completes the PNP irp for SMB mini redirector.
|
||
|
||
Arguments:
|
||
|
||
DeviceObject - Supplies the device object for the packet being processed.
|
||
|
||
pIrp - Supplies the Irp being processed
|
||
|
||
pContext - the completion context
|
||
|
||
--*/
|
||
{
|
||
PKEVENT pCompletionEvent = pContext;
|
||
|
||
KeSetEvent(
|
||
pCompletionEvent,
|
||
IO_NO_INCREMENT,
|
||
FALSE);
|
||
|
||
return STATUS_MORE_PROCESSING_REQUIRED;
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
MRxSmbProcessPnpIrp(
|
||
PIRP pIrp)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine initiates the processing of PNP irps for SMB mini redirector.
|
||
|
||
Arguments:
|
||
|
||
pIrp - Supplies the Irp being processed
|
||
|
||
Notes:
|
||
|
||
The query target device relation is the only call that is implemented
|
||
currently. This is done by returing the PDO associated with the transport
|
||
connection object. In any case this routine assumes the responsibility of
|
||
completing the IRP and return STATUS_PENDING.
|
||
|
||
This routine also writes an error log entry when the underlying transport
|
||
fails the request. This should help us isolate the responsibility.
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS Status;
|
||
|
||
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( pIrp );
|
||
|
||
IoMarkIrpPending(pIrp);
|
||
|
||
if ((IrpSp->MinorFunction == IRP_MN_QUERY_DEVICE_RELATIONS) &&
|
||
(IrpSp->Parameters.QueryDeviceRelations.Type==TargetDeviceRelation)) {
|
||
PIRP pAssociatedIrp;
|
||
PFILE_OBJECT pConnectionFileObject = NULL;
|
||
PMRX_FCB pFcb = NULL;
|
||
|
||
PSMBCEDB_SERVER_ENTRY pServerEntry = NULL;
|
||
BOOLEAN ServerTransportReferenced = FALSE;
|
||
|
||
// Locate the transport connection object for the associated file object
|
||
// and forward the query to that device.
|
||
|
||
if ((IrpSp->FileObject != NULL) &&
|
||
((pFcb = IrpSp->FileObject->FsContext) != NULL) &&
|
||
(NodeTypeIsFcb(pFcb))) {
|
||
PMRX_SRV_CALL pSrvCall;
|
||
PMRX_NET_ROOT pNetRoot;
|
||
|
||
if (((pNetRoot = pFcb->pNetRoot) != NULL) &&
|
||
((pSrvCall = pNetRoot->pSrvCall) != NULL)) {
|
||
pServerEntry = pSrvCall->Context;
|
||
|
||
if (pServerEntry != NULL) {
|
||
SmbCeAcquireResource();
|
||
|
||
Status = SmbCeReferenceServerTransport(&pServerEntry->pTransport);
|
||
|
||
if (Status == STATUS_SUCCESS) {
|
||
pConnectionFileObject = SmbCepReferenceEndpointFileObject(
|
||
pServerEntry->pTransport);
|
||
|
||
ServerTransportReferenced = TRUE;
|
||
}
|
||
|
||
SmbCeReleaseResource();
|
||
}
|
||
}
|
||
}
|
||
|
||
if (pConnectionFileObject != NULL) {
|
||
PDEVICE_OBJECT pRelatedDeviceObject;
|
||
PIO_STACK_LOCATION pIrpStackLocation,
|
||
pAssociatedIrpStackLocation;
|
||
|
||
pRelatedDeviceObject = IoGetRelatedDeviceObject(pConnectionFileObject);
|
||
|
||
pAssociatedIrp = IoAllocateIrp(
|
||
pRelatedDeviceObject->StackSize,
|
||
FALSE);
|
||
|
||
if (pAssociatedIrp != NULL) {
|
||
KEVENT CompletionEvent;
|
||
|
||
KeInitializeEvent( &CompletionEvent,
|
||
SynchronizationEvent,
|
||
FALSE );
|
||
|
||
// Fill up the associated IRP and call the underlying driver.
|
||
pAssociatedIrpStackLocation = IoGetNextIrpStackLocation(pAssociatedIrp);
|
||
pIrpStackLocation = IoGetCurrentIrpStackLocation(pIrp);
|
||
|
||
*pAssociatedIrpStackLocation = *pIrpStackLocation;
|
||
|
||
pAssociatedIrpStackLocation->FileObject = pConnectionFileObject;
|
||
pAssociatedIrpStackLocation->DeviceObject = pRelatedDeviceObject;
|
||
|
||
IoSetCompletionRoutine(
|
||
pAssociatedIrp,
|
||
MRxSmbPnpIrpCompletion,
|
||
&CompletionEvent,
|
||
TRUE,TRUE,TRUE);
|
||
|
||
pAssociatedIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
||
|
||
Status = IoCallDriver(pRelatedDeviceObject,pAssociatedIrp);
|
||
|
||
if (Status == STATUS_PENDING) {
|
||
(VOID) KeWaitForSingleObject(
|
||
&CompletionEvent,
|
||
Executive,
|
||
KernelMode,
|
||
FALSE,
|
||
(PLARGE_INTEGER) NULL );
|
||
}
|
||
|
||
pIrp->IoStatus = pAssociatedIrp->IoStatus;
|
||
Status = pIrp->IoStatus.Status;
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
MRxSmbLogTransportError(
|
||
&pServerEntry->pTransport->pTransport->RxCeTransport.Name,
|
||
&SmbCeContext.DomainName,
|
||
Status,
|
||
EVENT_RDR_CONNECTION);
|
||
}
|
||
|
||
ObDereferenceObject(pConnectionFileObject);
|
||
|
||
IoFreeIrp(pAssociatedIrp);
|
||
} else {
|
||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
} else {
|
||
Status = STATUS_INVALID_DEVICE_REQUEST;
|
||
}
|
||
|
||
if (ServerTransportReferenced) {
|
||
SmbCeDereferenceServerTransport(&pServerEntry->pTransport);
|
||
}
|
||
} else {
|
||
Status = STATUS_INVALID_DEVICE_REQUEST;
|
||
}
|
||
|
||
if (Status != STATUS_PENDING) {
|
||
pIrp->IoStatus.Status = Status;
|
||
IoCompleteRequest(pIrp,IO_NO_INCREMENT);
|
||
Status = STATUS_PENDING;
|
||
}
|
||
|
||
return STATUS_PENDING;
|
||
}
|
||
|
||
WML_CONTROL_GUID_REG MRxSmb_ControlGuids[] = {
|
||
{ // 8fc7e81a-f733-42e0-9708-cfdae07ed969 MRxSmb
|
||
0x8fc7e81a,0xf733,0x42e0,{0x97,0x08,0xcf,0xda,0xe0,0x7e,0xd9,0x69},
|
||
{ // eab93e5c-02ce-4e33-9419-901d82868816
|
||
{0xeab93e5c,0x02ce,0x4e33,{0x94,0x19,0x90,0x1d,0x82,0x86,0x88,0x16},},
|
||
// 56a0dee7-be12-4cf1-b7e0-976b0d174944
|
||
{0x56a0dee7,0xbe12,0x4cf1,{0xb7,0xe0,0x97,0x6b,0x0d,0x17,0x49,0x44},},
|
||
// ecabc730-60bf-481e-b92b-2749f8272d9d
|
||
{0xecabc730,0x60bf,0x481e,{0xb9,0x2b,0x27,0x49,0xf8,0x27,0x2d,0x9d},}
|
||
},
|
||
},
|
||
};
|
||
|
||
#define MRxSmb_ControlGuids_len 1
|
||
|
||
NTSTATUS
|
||
MRxSmbProcessSystemControlIrp(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PIRP Irp
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This is the common routine for doing System control operations called
|
||
by both the fsd and fsp threads
|
||
|
||
Arguments:
|
||
|
||
Irp - Supplies the Irp to process
|
||
|
||
InFsp - Indicates if this is the fsp thread or someother thread
|
||
|
||
Return Value:
|
||
|
||
RXSTATUS - The return status for the operation
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS Status;
|
||
|
||
WML_TINY_INFO Info;
|
||
UNICODE_STRING RegPath;
|
||
|
||
PAGED_CODE();
|
||
|
||
if (EnableWmiLog) {
|
||
RtlInitUnicodeString (&RegPath, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\MRxSmb");
|
||
|
||
RtlZeroMemory (&Info, sizeof(Info));
|
||
|
||
Info.ControlGuids = MRxSmb_ControlGuids;
|
||
Info.GuidCount = MRxSmb_ControlGuids_len;
|
||
Info.DriverRegPath = &RegPath;
|
||
|
||
Status = WmlTinySystemControl(&Info,DeviceObject,Irp);
|
||
|
||
if (Status != STATUS_SUCCESS) {
|
||
//DbgPrint("MRxSmb WMI control return %lx\n", Status);
|
||
}
|
||
} else {
|
||
Status = STATUS_INVALID_DEVICE_REQUEST;
|
||
Irp->IoStatus.Status = Status;
|
||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||
}
|
||
|
||
return Status;
|
||
}
|
||
|
||
extern LONG BowserDebugTraceLevel;
|
||
NTSTATUS
|
||
MRxSmbFsdDispatch (
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PIRP Irp
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine implements the FSD dispatch for the smbmini DRIVER object.
|
||
|
||
Arguments:
|
||
|
||
DeviceObject - Supplies the device object for the packet being processed.
|
||
|
||
Irp - Supplies the Irp being processed
|
||
|
||
Return Value:
|
||
|
||
RXSTATUS - The Fsd status for the Irp
|
||
|
||
Notes:
|
||
|
||
This routine centralizes the logic required to dela with special cases in
|
||
handling various requests directed to the redirector.
|
||
|
||
1) The Browser is built as part of the redirector driver ( mrxsmb.sys ) for
|
||
historical reasons ( carryover effect from the old redirector ). Hence this
|
||
routine serves as the switching point for redirecting requests to the browser
|
||
or the redirector depending on the device object.
|
||
|
||
2) The browser occasionally specifies a transport name in its open requests.
|
||
This is a request by the browser to override the transport priority
|
||
otherwise specified. In such cases this routine invokes the appropriate
|
||
preprocessing before passing on the request to the wrapper.
|
||
|
||
3) The DFS driver also specifies additional parameters in its open requests.
|
||
In such cases this routine invokes the appropriate preprocessing routine.
|
||
|
||
4) The PNP IRP for returning device relations are subverted by the mini
|
||
redirector for SMB
|
||
|
||
(2) (3) and (4) are legitimate uses of the wrapper architecture in which each
|
||
mini redirector is given the ability to customize the response to IRPs
|
||
passed in by the I/O subsystem. This is typically done by overiding the
|
||
dispatch vector.
|
||
|
||
--*/
|
||
{
|
||
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp ); //ok4ioget
|
||
UCHAR MajorFunctionCode = IrpSp->MajorFunction;
|
||
ULONG MinorFunctionCode = IrpSp->MinorFunction;
|
||
BOOLEAN ForwardRequestToWrapper = TRUE;
|
||
|
||
PSMBCEDB_SERVER_ENTRY pServerEntry = NULL;
|
||
NTSTATUS Status;
|
||
|
||
|
||
PAGED_CODE();
|
||
|
||
if (DeviceObject == (PDEVICE_OBJECT)BowserDeviceObject) {
|
||
switch (MajorFunctionCode) {
|
||
case IRP_MJ_DEVICE_CONTROL:
|
||
{
|
||
ULONG IoControlCode = IrpSp->Parameters.DeviceIoControl.IoControlCode;
|
||
|
||
Status = BowserFsdDeviceIoControlFile(BowserDeviceObject, Irp);
|
||
|
||
if ((Status == STATUS_SUCCESS) &&
|
||
(MinorFunctionCode == IRP_MN_USER_FS_REQUEST) &&
|
||
(IoControlCode == IOCTL_LMDR_START)) {
|
||
|
||
MRxSmbRegisterForPnpNotifications();
|
||
}
|
||
}
|
||
|
||
return Status;
|
||
|
||
case IRP_MJ_QUERY_INFORMATION:
|
||
return BowserFsdQueryInformationFile(BowserDeviceObject, Irp);
|
||
|
||
case IRP_MJ_CREATE:
|
||
return BowserFsdCreate(BowserDeviceObject, Irp);
|
||
|
||
case IRP_MJ_CLEANUP:
|
||
return BowserFsdCleanup(BowserDeviceObject, Irp);
|
||
|
||
case IRP_MJ_CLOSE:
|
||
return BowserFsdClose(BowserDeviceObject, Irp);
|
||
|
||
default:
|
||
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
|
||
Irp->IoStatus.Information = 0;
|
||
IoCompleteRequest(Irp, IO_NO_INCREMENT );
|
||
return (STATUS_NOT_IMPLEMENTED);
|
||
}
|
||
}
|
||
|
||
ASSERT(DeviceObject==(PDEVICE_OBJECT)MRxSmbDeviceObject);
|
||
if (DeviceObject!=(PDEVICE_OBJECT)MRxSmbDeviceObject) {
|
||
Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
|
||
Irp->IoStatus.Information = 0;
|
||
IoCompleteRequest(Irp, IO_NO_INCREMENT );
|
||
return (STATUS_INVALID_DEVICE_REQUEST);
|
||
}
|
||
|
||
if (IrpSp->MajorFunction == IRP_MJ_SYSTEM_CONTROL) {
|
||
return MRxSmbProcessSystemControlIrp(DeviceObject,Irp);
|
||
}
|
||
|
||
Status = STATUS_SUCCESS;
|
||
|
||
FsRtlEnterFileSystem();
|
||
|
||
if (IrpSp->MajorFunction == IRP_MJ_PNP) {
|
||
ForwardRequestToWrapper = FALSE;
|
||
Status = MRxSmbProcessPnpIrp(Irp);
|
||
} else {
|
||
if (IrpSp->MajorFunction == IRP_MJ_CREATE) {
|
||
Status = CscPreProcessCreateIrp(Irp);
|
||
}
|
||
|
||
if (Status == STATUS_SUCCESS) {
|
||
Status = MRxSmbCheckTransportName(Irp, &pServerEntry);
|
||
}
|
||
}
|
||
|
||
FsRtlExitFileSystem();
|
||
|
||
if ((Status == STATUS_SUCCESS) &&
|
||
ForwardRequestToWrapper){
|
||
Status = RxFsdDispatch((PRDBSS_DEVICE_OBJECT)MRxSmbDeviceObject,Irp);
|
||
} else if (Status != STATUS_PENDING) {
|
||
Irp->IoStatus.Status = Status;
|
||
Irp->IoStatus.Information = 0;
|
||
IoCompleteRequest(Irp, IO_NO_INCREMENT );
|
||
}
|
||
|
||
if (pServerEntry != NULL ) {
|
||
FsRtlEnterFileSystem();
|
||
|
||
pServerEntry->TransportSpecifiedByUser = 0;
|
||
SmbCeDereferenceServerEntry(pServerEntry);
|
||
|
||
FsRtlExitFileSystem();
|
||
}
|
||
|
||
return Status;
|
||
}
|
||
|
||
NTSTATUS
|
||
MRxSmbDeallocateForFcb (
|
||
IN OUT PMRX_FCB pFcb
|
||
)
|
||
{
|
||
PAGED_CODE();
|
||
|
||
MRxSmbCscDeallocateForFcb(pFcb);
|
||
return(STATUS_SUCCESS);
|
||
}
|
||
|
||
NTSTATUS
|
||
MRxSmbDeallocateForFobx (
|
||
IN OUT PMRX_FOBX pFobx
|
||
)
|
||
{
|
||
|
||
PAGED_CODE();
|
||
|
||
IF_DEBUG {
|
||
PMRX_SMB_FOBX smbFobx = MRxSmbGetFileObjectExtension(pFobx);
|
||
PMRX_SRV_OPEN SrvOpen = pFobx->pSrvOpen;
|
||
PMRX_FCB Fcb = SrvOpen->pFcb;
|
||
|
||
if (smbFobx && FlagOn(smbFobx->Enumeration.Flags,SMBFOBX_ENUMFLAG_LOUD_FINALIZE)) {
|
||
DbgPrint("Finalizobx side buffer %p %p %p %pon %wZ\n",
|
||
0, 0, // sidebuffer, count
|
||
smbFobx,pFobx,GET_ALREADY_PREFIXED_NAME(SrvOpen,Fcb)
|
||
);
|
||
}
|
||
}
|
||
|
||
return(STATUS_SUCCESS);
|
||
}
|
||
|
||
NTSTATUS
|
||
MRxSmbDeleteRegistryParameter(
|
||
HANDLE ParametersHandle,
|
||
PWCHAR ParameterName
|
||
)
|
||
{
|
||
UNICODE_STRING UnicodeString;
|
||
NTSTATUS Status;
|
||
|
||
PAGED_CODE(); //INIT
|
||
|
||
RtlInitUnicodeString(&UnicodeString, ParameterName);
|
||
|
||
Status = ZwDeleteValueKey(ParametersHandle,
|
||
&UnicodeString);
|
||
|
||
ASSERT(NT_SUCCESS(Status));
|
||
|
||
return(Status);
|
||
|
||
}
|
||
|
||
NTSTATUS
|
||
MRxSmbGetUlongRegistryParameter(
|
||
HANDLE ParametersHandle,
|
||
PWCHAR ParameterName,
|
||
PULONG ParamUlong,
|
||
BOOLEAN LogFailure
|
||
)
|
||
{
|
||
ULONG Storage[16];
|
||
PKEY_VALUE_PARTIAL_INFORMATION Value;
|
||
ULONG ValueSize;
|
||
UNICODE_STRING UnicodeString;
|
||
NTSTATUS Status;
|
||
ULONG BytesRead;
|
||
|
||
PAGED_CODE(); //INIT
|
||
|
||
Value = (PKEY_VALUE_PARTIAL_INFORMATION)Storage;
|
||
ValueSize = sizeof(Storage);
|
||
|
||
RtlInitUnicodeString(&UnicodeString, ParameterName);
|
||
|
||
Status = ZwQueryValueKey(ParametersHandle,
|
||
&UnicodeString,
|
||
KeyValuePartialInformation,
|
||
Value,
|
||
ValueSize,
|
||
&BytesRead);
|
||
|
||
|
||
if (NT_SUCCESS(Status)) {
|
||
if (Value->Type == REG_DWORD) {
|
||
PULONG ConfigValue = (PULONG)&Value->Data[0];
|
||
*ParamUlong = *((PULONG)ConfigValue);
|
||
return(STATUS_SUCCESS);
|
||
} else {
|
||
Status = STATUS_INVALID_PARAMETER;
|
||
}
|
||
}
|
||
|
||
if (!LogFailure) { return Status; }
|
||
|
||
RxLogFailureWithBuffer(
|
||
MRxSmbDeviceObject,
|
||
NULL,
|
||
EVENT_RDR_CANT_READ_REGISTRY,
|
||
Status,
|
||
ParameterName,
|
||
(USHORT)(wcslen(ParameterName)*sizeof(WCHAR))
|
||
);
|
||
|
||
return Status;
|
||
}
|
||
|
||
NTSTATUS
|
||
SmbCeGetServersWithExtendedSessTimeout()
|
||
{
|
||
ULONG Storage[256];
|
||
UNICODE_STRING UnicodeString;
|
||
HANDLE hRegistryKey;
|
||
NTSTATUS Status;
|
||
ULONG BytesRead;
|
||
|
||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||
PKEY_VALUE_FULL_INFORMATION Value = (PKEY_VALUE_FULL_INFORMATION)Storage;
|
||
KEY_VALUE_PARTIAL_INFORMATION InitialPartialInformationValue;
|
||
ULONG AllocationLength;
|
||
PKEY_VALUE_PARTIAL_INFORMATION ServersValueFromRegistry;
|
||
|
||
PAGED_CODE();
|
||
|
||
// Obtain the list of servers associated with extended session timeout.
|
||
|
||
// This is required by third party server which handles SMB sessions with different processes.
|
||
// The time to process requests on different sessions can be varied dramatically.
|
||
|
||
RtlInitUnicodeString(&UnicodeString, SMBMRX_WORKSTATION_PARAMETERS);
|
||
|
||
InitializeObjectAttributes(
|
||
&ObjectAttributes,
|
||
&UnicodeString, // name
|
||
OBJ_CASE_INSENSITIVE, // attributes
|
||
NULL, // root
|
||
NULL); // security descriptor
|
||
|
||
Status = ZwOpenKey (&hRegistryKey, KEY_READ, &ObjectAttributes);
|
||
if (!NT_SUCCESS(Status)) {
|
||
//DbgPrint("SmbCeGetServersWithExtendedSessTimeout ZwOpenKey failed %x\n",Status);
|
||
return Status;
|
||
}
|
||
|
||
RtlInitUnicodeString(&UnicodeString, L"ServersWithExtendedSessTimeout");
|
||
Status = ZwQueryValueKey(
|
||
hRegistryKey,
|
||
&UnicodeString,
|
||
KeyValuePartialInformation,
|
||
&InitialPartialInformationValue,
|
||
sizeof(InitialPartialInformationValue),
|
||
&BytesRead);
|
||
if (Status== STATUS_BUFFER_OVERFLOW) {
|
||
Status = STATUS_SUCCESS;
|
||
}
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
ZwClose(hRegistryKey);
|
||
return Status;
|
||
}
|
||
|
||
AllocationLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION)
|
||
+ InitialPartialInformationValue.DataLength;
|
||
if (0) {
|
||
DbgPrint("SizeofBindingInfo=%08lx %08lx\n",
|
||
AllocationLength,
|
||
InitialPartialInformationValue.DataLength);
|
||
}
|
||
|
||
ASSERT(SmbCeContext.ServersWithExtendedSessTimeout.Buffer == NULL);
|
||
|
||
(PBYTE)ServersValueFromRegistry = RxAllocatePoolWithTag(
|
||
PagedPool,
|
||
AllocationLength,
|
||
MRXSMB_MISC_POOLTAG);
|
||
|
||
if (ServersValueFromRegistry == NULL) {
|
||
ZwClose(hRegistryKey);
|
||
return(STATUS_INSUFFICIENT_RESOURCES);
|
||
}
|
||
|
||
Status = ZwQueryValueKey(
|
||
hRegistryKey,
|
||
&UnicodeString,
|
||
KeyValuePartialInformation,
|
||
ServersValueFromRegistry,
|
||
AllocationLength,
|
||
&BytesRead);
|
||
|
||
if (NT_SUCCESS(Status) &&
|
||
(ServersValueFromRegistry->DataLength > 0) &&
|
||
(ServersValueFromRegistry->Type == REG_MULTI_SZ)) {
|
||
|
||
SmbCeContext.ServersWithExtendedSessTimeout.MaximumLength =
|
||
SmbCeContext.ServersWithExtendedSessTimeout.Length = (USHORT)ServersValueFromRegistry->DataLength;
|
||
SmbCeContext.ServersWithExtendedSessTimeout.Buffer = (PWCHAR)(&ServersValueFromRegistry->Data[0]);
|
||
//DbgPrint("b1 %08lx b2 %08lx\n", ServersValueFromRegistry,SmbCeContext.ServersWithExtendedSessTimeout.Buffer);
|
||
} else {
|
||
RxLog(("Invalid Transport Binding string... using all transports"));
|
||
SmbLog(LOG,
|
||
SmbCeGetConfigurationInformation,
|
||
LOGULONG(Status));
|
||
RxFreePool(ServersValueFromRegistry);
|
||
ServersValueFromRegistry = NULL;
|
||
}
|
||
|
||
ZwClose(hRegistryKey);
|
||
|
||
return Status;
|
||
}
|
||
|
||
|
||
|