1443 lines
39 KiB
C
1443 lines
39 KiB
C
|
||
/*++
|
||
|
||
Copyright (c) 1989 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
RxInit.c
|
||
|
||
Abstract:
|
||
|
||
This module implements the DRIVER_INITIALIZATION routine for the RDBSS.
|
||
|
||
Also, the routines for pagingio resource selection/allocation are here; since
|
||
we have to delete the resources when we unload, having them here simply centralizes
|
||
all the pagingio resource stuff.
|
||
|
||
Finally, the routines that are here that implement the wrapper's version of
|
||
network provider order. Basically, the wrapper MUST implement the same concept of
|
||
network provider order as the MUP so that the UI will work as expected. So, we
|
||
read the provider order from the registry at init time and memorize the order. Then,
|
||
we can assign the correct order when minirdrs register. Obviously, provider order is
|
||
not an issue in MONOLITHIC mode.
|
||
|
||
Author:
|
||
|
||
Joe Linn [JoeLinn] 20-jul-1994
|
||
|
||
Revision History:
|
||
|
||
|
||
--*/
|
||
|
||
#include "precomp.h"
|
||
#pragma hdrstop
|
||
#include "ntverp.h"
|
||
#include "NtDdNfs2.h"
|
||
#include "netevent.h"
|
||
|
||
//
|
||
// The local debug trace level
|
||
//
|
||
|
||
#define Dbg (0)
|
||
|
||
ULONG RxBuildNumber = VER_PRODUCTBUILD;
|
||
#ifdef RX_PRIVATE_BUILD
|
||
ULONG RxPrivateBuild = 1;
|
||
#else
|
||
ULONG RxPrivateBuild = 0;
|
||
#endif
|
||
|
||
#ifdef MONOLITHIC_MINIRDR
|
||
RDBSS_DEVICE_OBJECT RxSpaceForTheWrappersDeviceObject;
|
||
#endif
|
||
|
||
#define LANMAN_WORKSTATION_PARAMETERS \
|
||
L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\LanmanWorkStation\\Parameters"
|
||
|
||
BOOLEAN DisableByteRangeLockingOnReadOnlyFiles = FALSE;
|
||
|
||
VOID
|
||
RxReadRegistryParameters();
|
||
|
||
NPAGED_LOOKASIDE_LIST RxContextLookasideList;
|
||
|
||
VOID
|
||
RxGetRegistryParameters(
|
||
IN PUNICODE_STRING RegistryPath
|
||
);
|
||
|
||
NTSTATUS
|
||
RxInitializeRegistrationStructures(
|
||
void
|
||
);
|
||
VOID
|
||
RxUninitializeRegistrationStructures(
|
||
void
|
||
);
|
||
|
||
VOID
|
||
RxAbbreviatedWriteLogEntry__ (
|
||
IN NTSTATUS Status,
|
||
IN ULONG OneExtraUlong
|
||
);
|
||
#define RxAbbreviatedWriteLogEntry(STATUS__) RxAbbreviatedWriteLogEntry__(STATUS__,__LINE__)
|
||
|
||
|
||
NTSTATUS
|
||
RxGetStringRegistryParameter(
|
||
HANDLE ParametersHandle,
|
||
PWCHAR ParameterName,
|
||
PUNICODE_STRING ParamString,
|
||
PKEY_VALUE_PARTIAL_INFORMATION Value,
|
||
ULONG ValueSize,
|
||
BOOLEAN LogFailure
|
||
);
|
||
|
||
NTSTATUS
|
||
RxGetUlongRegistryParameter(
|
||
HANDLE ParametersHandle,
|
||
PWCHAR ParameterName,
|
||
PULONG ParamUlong,
|
||
PKEY_VALUE_PARTIAL_INFORMATION Value,
|
||
ULONG ValueSize,
|
||
BOOLEAN LogFailure
|
||
);
|
||
|
||
//this type and variable are used for unwinding the initialization so that stuff doesn't go thru the cracks
|
||
// the way that this works is that stuff is done in the reverse order of the enumeration. that way i can just
|
||
// use a switch-no-break to unwind.
|
||
typedef enum _RX_INIT_STATES {
|
||
RXINIT_ALL_INITIALIZATION_COMPLETED,
|
||
RXINIT_CONSTRUCTED_PROVIDERORDER,
|
||
RXINIT_CREATED_LOG,
|
||
RXINIT_CREATED_DEVICE_OBJECT,
|
||
RXINIT_CREATED_FIRST_LINK,
|
||
RXINIT_START
|
||
} RX_INIT_STATES;
|
||
|
||
VOID
|
||
RxInitUnwind(
|
||
IN PDRIVER_OBJECT DriverObject,
|
||
IN RX_INIT_STATES RxInitState
|
||
);
|
||
|
||
#ifdef ALLOC_PRAGMA
|
||
#pragma alloc_text(INIT, RxDriverEntry)
|
||
#pragma alloc_text(INIT, RxGetRegistryParameters)
|
||
#pragma alloc_text(INIT, RxGetStringRegistryParameter)
|
||
#pragma alloc_text(INIT, RxGetUlongRegistryParameter)
|
||
#pragma alloc_text(INIT, RxAbbreviatedWriteLogEntry__)
|
||
#pragma alloc_text(PAGE, RxUnload)
|
||
#pragma alloc_text(PAGE, RxInitUnwind)
|
||
#pragma alloc_text(PAGE, RxGetNetworkProviderPriority)
|
||
#pragma alloc_text(PAGE, RxInitializeRegistrationStructures)
|
||
#pragma alloc_text(PAGE, RxUninitializeRegistrationStructures)
|
||
#pragma alloc_text(PAGE, RxInitializeMinirdrDispatchTable)
|
||
#pragma alloc_text(PAGE, __RxFillAndInstallFastIoDispatch)
|
||
#pragma alloc_text(PAGE, RxReadRegistryParameters)
|
||
#endif
|
||
|
||
#define RX_SYMLINK_NAME L"\\??\\fsWrap"
|
||
|
||
BOOLEAN EnableWmiLog = FALSE;
|
||
|
||
NTSTATUS
|
||
RxDriverEntry(
|
||
IN PDRIVER_OBJECT DriverObject,
|
||
IN PUNICODE_STRING RegistryPath
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This is the initialization routine for the Rx file system
|
||
device driver. This routine creates the device object for the FileSystem
|
||
device and performs all other driver initialization.
|
||
|
||
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;
|
||
RX_INIT_STATES RxInitState = 0;
|
||
#ifndef MONOLITHIC_MINIRDR
|
||
UNICODE_STRING UnicodeString,LinkName;
|
||
#endif
|
||
|
||
//Structure checks
|
||
RxCheckFcbStructuresForAlignment(); //this will bugcheck if things are bad
|
||
|
||
//
|
||
// Initialize the global data structures
|
||
|
||
|
||
ZeroAndInitializeNodeType( &RxData, RDBSS_NTC_DATA_HEADER, sizeof(RDBSS_DATA));
|
||
RxData.DriverObject = DriverObject;
|
||
|
||
ZeroAndInitializeNodeType( &RxDeviceFCB, RDBSS_NTC_DEVICE_FCB, sizeof(FCB));
|
||
|
||
KeInitializeSpinLock( &RxStrucSupSpinLock );
|
||
RxExports.pRxStrucSupSpinLock = &RxStrucSupSpinLock;
|
||
|
||
RxInitializeDebugSupport();
|
||
|
||
try {
|
||
|
||
Status = RXINIT_START;
|
||
|
||
#ifndef MONOLITHIC_MINIRDR
|
||
//
|
||
// Create a symbolic link from \\dosdevices\fswrap to the rdbss device object name
|
||
|
||
RtlInitUnicodeString(&LinkName, RX_SYMLINK_NAME);
|
||
RtlInitUnicodeString(&UnicodeString, DD_NFS2_DEVICE_NAME_U);
|
||
|
||
IoDeleteSymbolicLink(&LinkName);
|
||
Status = IoCreateSymbolicLink(&LinkName, &UnicodeString);
|
||
|
||
if (!NT_SUCCESS( Status )) {
|
||
try_return( Status );
|
||
}
|
||
RxInitState = RXINIT_CREATED_FIRST_LINK;
|
||
|
||
//
|
||
// Create the device object.
|
||
|
||
Status = IoCreateDevice(DriverObject,
|
||
sizeof(RDBSS_DEVICE_OBJECT) - sizeof(DEVICE_OBJECT),
|
||
&UnicodeString,
|
||
FILE_DEVICE_NETWORK_FILE_SYSTEM,
|
||
FILE_REMOTE_DEVICE,
|
||
FALSE,
|
||
(PDEVICE_OBJECT *)(&RxFileSystemDeviceObject));
|
||
|
||
if (!NT_SUCCESS( Status )) {
|
||
try_return( Status );
|
||
}
|
||
RxInitState = RXINIT_CREATED_DEVICE_OBJECT;
|
||
|
||
#else
|
||
|
||
// in monolithic mode, the wrapper doesn't really need a device object but
|
||
// we allocate stuff in the wrapper's device object in order to appropriately throttle
|
||
// thread usage per device object.
|
||
RxFileSystemDeviceObject = &RxSpaceForTheWrappersDeviceObject;
|
||
RtlZeroMemory(RxFileSystemDeviceObject,sizeof(RxSpaceForTheWrappersDeviceObject));
|
||
|
||
#endif
|
||
//
|
||
// Initialize the trace and logging facilities. loginit is a big allocation.
|
||
|
||
RxInitializeDebugTrace();
|
||
|
||
RxInitializeLog();
|
||
|
||
RxInitState = RXINIT_CREATED_LOG;
|
||
|
||
RxGetRegistryParameters(RegistryPath);
|
||
RxDbgTrace(0, (DEBUG_TRACE_ALWAYS), ("Constants %08lx %08lx\n",
|
||
RX_CONTEXT_FLAG_WAIT,
|
||
RX_CONTEXT_CREATE_FLAG_ADDEDBACKSLASH
|
||
));
|
||
|
||
RxReadRegistryParameters();
|
||
|
||
//
|
||
// Initialize the minirdr registration facilities.
|
||
|
||
Status = RxInitializeRegistrationStructures();
|
||
|
||
if (!NT_SUCCESS( Status )) {
|
||
try_return( Status );
|
||
}
|
||
RxInitState = RXINIT_CONSTRUCTED_PROVIDERORDER;
|
||
|
||
try_exit: NOTHING;
|
||
} finally {
|
||
if (Status != STATUS_SUCCESS) {
|
||
RxLogFailure (
|
||
RxFileSystemDeviceObject,
|
||
NULL,
|
||
EVENT_RDR_UNEXPECTED_ERROR,
|
||
Status);
|
||
|
||
RxInitUnwind(DriverObject,RxInitState);
|
||
}
|
||
}
|
||
|
||
if (Status != STATUS_SUCCESS) {
|
||
return(Status);
|
||
}
|
||
|
||
//
|
||
//
|
||
//
|
||
//
|
||
// ##### ## # # #### ###### #####
|
||
// # # # # ## # # # # # #
|
||
// # # # # # # # # ##### # #
|
||
// # # ###### # # # # ### # #####
|
||
// # # # # # ## # # # # #
|
||
// ##### # # # # #### ###### # #
|
||
//
|
||
//
|
||
//
|
||
// EVERYTHING FROM HERE DOWN BETTER WORK BECAUSE THERE IS NO MORE UNWINDING!!!
|
||
//
|
||
//
|
||
|
||
|
||
RxInitializeDispatcher();
|
||
RxInitializeBackoffPackage();
|
||
|
||
// Initialize the look aside list for RxContext allocation
|
||
ExInitializeNPagedLookasideList(
|
||
&RxContextLookasideList,
|
||
ExAllocatePoolWithTag,
|
||
ExFreePool,
|
||
0,
|
||
sizeof(RX_CONTEXT),
|
||
RX_IRPC_POOLTAG,
|
||
4);
|
||
|
||
// Initialize the list of transport Irps to an empty list
|
||
InitializeListHead(&RxIrpsList);
|
||
KeInitializeSpinLock(&RxIrpsListSpinLock);
|
||
|
||
// Initialize the list of active contexts to an empty list
|
||
InitializeListHead(&RxActiveContexts);
|
||
|
||
// Initialize the list of srv call downs active
|
||
InitializeListHead(&RxSrvCalldownList);
|
||
|
||
// a fastmutex is used to serialize access to the Qs that serialize blocking pipe operations
|
||
ExInitializeFastMutex(&RxContextPerFileSerializationMutex);
|
||
|
||
// and to serialize access to the Qs that serialize some pagingio operations
|
||
ExInitializeFastMutex(&RxLowIoPagingIoSyncMutex);
|
||
|
||
// Initialize the scavenger mutex
|
||
KeInitializeMutex(&RxScavengerMutex,1);
|
||
|
||
// Initialize the global serialization Mutex.
|
||
KeInitializeMutex(&RxSerializationMutex,1);
|
||
|
||
//
|
||
// Initialize the wrapper's overflow queue
|
||
//
|
||
|
||
{
|
||
PRDBSS_DEVICE_OBJECT MyDo = (PRDBSS_DEVICE_OBJECT)RxFileSystemDeviceObject;
|
||
LONG Index;
|
||
|
||
for (Index = 0; Index < MaximumWorkQueue; Index++) {
|
||
MyDo->OverflowQueueCount[Index] = 0;
|
||
|
||
InitializeListHead( &MyDo->OverflowQueue[Index] );
|
||
|
||
MyDo->PostedRequestCount[Index] = 0;
|
||
}
|
||
|
||
KeInitializeSpinLock( &MyDo->OverflowQueueSpinLock );
|
||
}
|
||
|
||
//
|
||
// Initialize dispatch vector for driver object AND ALSO FOR the devicefcb
|
||
|
||
RxInitializeDispatchVectors(DriverObject);
|
||
ExInitializeResourceLite( &RxData.Resource );
|
||
|
||
//
|
||
// Set up global pointer to our process.
|
||
|
||
RxData.OurProcess = PsGetCurrentProcess();
|
||
|
||
//
|
||
// Put in a bunch of sanity checks about various structures...hey, it's init code!
|
||
|
||
IF_DEBUG {
|
||
ULONG FcbStateBufferingMask = FCB_STATE_BUFFERING_STATE_MASK;
|
||
ULONG MinirdrBufStateCommandMask = MINIRDR_BUFSTATE_COMMAND_MASK;
|
||
USHORT EightBitsPerChar = 8;
|
||
|
||
//we could put in defines for the ULONG/USHORTS here...but they don't change often
|
||
ASSERT ( MRDRBUFSTCMD_MAXXX == (sizeof(ULONG)*EightBitsPerChar) );
|
||
|
||
ASSERT (!(FcbStateBufferingMask&MinirdrBufStateCommandMask));
|
||
|
||
}
|
||
|
||
//
|
||
// Setup the timer subsystem
|
||
|
||
RxInitializeRxTimer();
|
||
|
||
#ifndef MONOLITHIC_MINIRDR
|
||
Status = IoWMIRegistrationControl ((PDEVICE_OBJECT)RxFileSystemDeviceObject, WMIREG_ACTION_REGISTER);
|
||
|
||
if (Status != STATUS_SUCCESS) {
|
||
DbgPrint("Rdbss fails to register WMI %lx\n",Status);
|
||
} else {
|
||
EnableWmiLog = TRUE;
|
||
}
|
||
#endif
|
||
|
||
return( STATUS_SUCCESS );
|
||
}
|
||
|
||
|
||
//
|
||
// Unload routine
|
||
//
|
||
|
||
VOID
|
||
RxUnload(
|
||
IN PDRIVER_OBJECT DriverObject
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This is the unload routine for the RDBSS.
|
||
|
||
Arguments:
|
||
|
||
DriverObject - pointer to the driver object for the RDBSS
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
|
||
{
|
||
//UNICODE_STRING LinkName;
|
||
|
||
PAGED_CODE();
|
||
|
||
RxTearDownRxTimer();
|
||
|
||
//remember this
|
||
// RdrUnloadSecurity();
|
||
|
||
RxDbgTrace( 0, (DEBUG_TRACE_ALWAYS), ("RxUnload: DriverObject =%08lx\n", DriverObject ));
|
||
|
||
ExDeleteResourceLite(&RxData.Resource);
|
||
|
||
RxUninitializeBackoffPackage();
|
||
|
||
RxTearDownDispatcher();
|
||
|
||
RxTearDownDebugSupport();
|
||
|
||
ExDeleteNPagedLookasideList(
|
||
&RxContextLookasideList);
|
||
|
||
RxInitUnwind(DriverObject, RXINIT_ALL_INITIALIZATION_COMPLETED);
|
||
|
||
if (EnableWmiLog) {
|
||
NTSTATUS Status;
|
||
|
||
Status = IoWMIRegistrationControl ((PDEVICE_OBJECT)RxFileSystemDeviceObject, WMIREG_ACTION_DEREGISTER);
|
||
if (Status != STATUS_SUCCESS) {
|
||
DbgPrint("Rdbss fails to deregister WMI %lx\n",Status);
|
||
}
|
||
}
|
||
}
|
||
|
||
#if DBG
|
||
PCHAR RxUnwindFollower = NULL;
|
||
#define UNWIND_CASE(x) case x: RxUnwindFollower = #x;
|
||
#else
|
||
#define UNWIND_CASE(x) case x:
|
||
#endif
|
||
|
||
|
||
|
||
VOID
|
||
RxInitUnwind(
|
||
IN PDRIVER_OBJECT DriverObject,
|
||
IN RX_INIT_STATES RxInitState
|
||
)
|
||
/*++
|
||
|
||
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
|
||
|
||
--*/
|
||
|
||
{
|
||
#ifndef MONOLITHIC_MINIRDR
|
||
UNICODE_STRING LinkName;
|
||
#endif
|
||
|
||
PAGED_CODE();
|
||
|
||
switch (RxInitState) {
|
||
UNWIND_CASE(RXINIT_ALL_INITIALIZATION_COMPLETED)
|
||
//Nothing extra to do...this is just so that the constant in RxUnload doesn't change.......
|
||
//lack of break intentional
|
||
|
||
UNWIND_CASE(RXINIT_CONSTRUCTED_PROVIDERORDER)
|
||
RxUninitializeRegistrationStructures();
|
||
//lack of break intentional
|
||
|
||
UNWIND_CASE(RXINIT_CREATED_LOG)
|
||
RxUninitializeLog();
|
||
//lack of break intentional
|
||
|
||
#ifndef MONOLITHIC_MINIRDR
|
||
UNWIND_CASE(RXINIT_CREATED_DEVICE_OBJECT)
|
||
IoDeleteDevice((PDEVICE_OBJECT)RxFileSystemDeviceObject);
|
||
//lack of break intentional
|
||
|
||
UNWIND_CASE(RXINIT_CREATED_FIRST_LINK)
|
||
RtlInitUnicodeString(&LinkName, RX_SYMLINK_NAME);
|
||
IoDeleteSymbolicLink(&LinkName);
|
||
// lack of break intentional
|
||
#endif
|
||
|
||
UNWIND_CASE(RXINIT_START)
|
||
//RdrUninitializeDiscardableCode();
|
||
//DbgBreakPoint();
|
||
break;
|
||
}
|
||
|
||
}
|
||
|
||
|
||
VOID
|
||
RxAbbreviatedWriteLogEntry__ (
|
||
IN NTSTATUS Status,
|
||
IN ULONG OneExtraUlong
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine write a log entry with most of the fields set to fixed values.
|
||
|
||
Arguments:
|
||
|
||
Status - the status to be stored in the log record
|
||
OneExtraUlong - a key for finding out what happened
|
||
|
||
Return Value:
|
||
|
||
none.
|
||
|
||
--*/
|
||
{
|
||
//RxLogFailureWithBuffer (
|
||
// RxFileSystemDeviceObject,
|
||
// NULL,
|
||
// EVENT_RDR_CANT_READ_REGISTRY,
|
||
// Status,
|
||
// &OneExtraUlong,
|
||
// sizeof(ULONG)
|
||
// );
|
||
}
|
||
|
||
|
||
VOID
|
||
RxGetRegistryParameters(
|
||
PUNICODE_STRING RegistryPath
|
||
)
|
||
{
|
||
ULONG Storage[256];
|
||
UNICODE_STRING UnicodeString;
|
||
HANDLE ConfigHandle;
|
||
HANDLE ParametersHandle;
|
||
NTSTATUS Status;
|
||
//ULONG BytesRead;
|
||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||
PKEY_VALUE_FULL_INFORMATION Value = (PKEY_VALUE_FULL_INFORMATION)Storage;
|
||
|
||
PAGED_CODE(); //INIT
|
||
|
||
InitializeObjectAttributes(
|
||
&ObjectAttributes,
|
||
RegistryPath, // name
|
||
OBJ_CASE_INSENSITIVE, // attributes
|
||
NULL, // root
|
||
NULL // security descriptor
|
||
);
|
||
|
||
Status = ZwOpenKey (&ConfigHandle, KEY_READ, &ObjectAttributes);
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
|
||
//RxLogFailure (
|
||
// RxFileSystemDeviceObject,
|
||
// NULL,
|
||
// EVENT_RDR_CANT_READ_REGISTRY,
|
||
// Status);
|
||
return;
|
||
}
|
||
|
||
RtlInitUnicodeString(&UnicodeString, L"Parameters");
|
||
|
||
InitializeObjectAttributes(
|
||
&ObjectAttributes,
|
||
&UnicodeString,
|
||
OBJ_CASE_INSENSITIVE,
|
||
ConfigHandle,
|
||
NULL
|
||
);
|
||
|
||
|
||
Status = ZwOpenKey (&ParametersHandle, KEY_READ, &ObjectAttributes);
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
|
||
//RxLogFailure (
|
||
// RxFileSystemDeviceObject,
|
||
// NULL,
|
||
// EVENT_RDR_CANT_READ_REGISTRY,
|
||
// Status);
|
||
|
||
ZwClose(ConfigHandle);
|
||
|
||
return;
|
||
}
|
||
|
||
#ifdef RDBSSLOG
|
||
RxGetStringRegistryParameter(ParametersHandle,
|
||
L"InitialDebugString",
|
||
&UnicodeString,
|
||
(PKEY_VALUE_PARTIAL_INFORMATION) Storage,
|
||
sizeof(Storage),
|
||
FALSE
|
||
);
|
||
|
||
|
||
//DbgPrint("String From Registry %wZ, buffer = %08lx\n",&UnicodeString,UnicodeString.Buffer);
|
||
if (UnicodeString.Length && UnicodeString.Length<320) {
|
||
PWCH u = UnicodeString.Buffer;
|
||
ULONG l;
|
||
PCH p = (PCH)u;
|
||
|
||
for (l=0;l<UnicodeString.Length;l++) {
|
||
*p++ = (CHAR)*u++;
|
||
*p = 0;
|
||
}
|
||
|
||
DbgPrint("InitialDebugString From Registry as singlebytestring: <%s>\n",UnicodeString.Buffer);
|
||
RxDebugControlCommand((PCH)UnicodeString.Buffer);
|
||
}
|
||
#endif //RDBSSLOG
|
||
|
||
ZwClose(ParametersHandle);
|
||
|
||
ZwClose(ConfigHandle);
|
||
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
RxGetStringRegistryParameter(
|
||
HANDLE ParametersHandle,
|
||
PWCHAR ParameterName,
|
||
PUNICODE_STRING ParamString,
|
||
PKEY_VALUE_PARTIAL_INFORMATION Value,
|
||
ULONG ValueSize,
|
||
BOOLEAN LogFailure
|
||
)
|
||
{
|
||
UNICODE_STRING UnicodeString;
|
||
NTSTATUS Status;
|
||
ULONG BytesRead;
|
||
|
||
PAGED_CODE(); //INIT
|
||
|
||
RtlInitUnicodeString(&UnicodeString, ParameterName);
|
||
|
||
Status = ZwQueryValueKey(ParametersHandle,
|
||
&UnicodeString,
|
||
KeyValuePartialInformation,
|
||
Value,
|
||
ValueSize,
|
||
&BytesRead);
|
||
|
||
ParamString->Length = 0;
|
||
ParamString->Buffer = NULL;
|
||
if (NT_SUCCESS(Status)) {
|
||
ParamString->Buffer = (PWCH)(&Value->Data[0]);
|
||
//the datalength actually accounts for the trailing null
|
||
ParamString->Length = ((USHORT)Value->DataLength) - sizeof(WCHAR);
|
||
ParamString->MaximumLength = ParamString->Length;
|
||
return STATUS_SUCCESS;
|
||
}
|
||
|
||
if (!LogFailure) { return Status; }
|
||
|
||
|
||
RxLogFailure (
|
||
RxFileSystemDeviceObject,
|
||
NULL,
|
||
EVENT_RDR_CANT_READ_REGISTRY,
|
||
Status);
|
||
|
||
return Status;
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
RxGetUlongRegistryParameter(
|
||
HANDLE ParametersHandle,
|
||
PWCHAR ParameterName,
|
||
PULONG ParamUlong,
|
||
PKEY_VALUE_PARTIAL_INFORMATION Value,
|
||
ULONG ValueSize,
|
||
BOOLEAN LogFailure
|
||
)
|
||
{
|
||
UNICODE_STRING UnicodeString;
|
||
NTSTATUS Status;
|
||
ULONG BytesRead;
|
||
|
||
PAGED_CODE(); //INIT
|
||
|
||
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);
|
||
DbgPrint("readRegistryvalue %wZ = %08lx\n",&UnicodeString,*ParamUlong);
|
||
return(STATUS_SUCCESS);
|
||
} else {
|
||
Status = STATUS_INVALID_PARAMETER;
|
||
}
|
||
}
|
||
|
||
if (!LogFailure) { return Status; }
|
||
|
||
RxLogFailureWithBuffer (
|
||
RxFileSystemDeviceObject,
|
||
NULL,
|
||
EVENT_RDR_CANT_READ_REGISTRY,
|
||
Status,
|
||
ParameterName,
|
||
(USHORT)(wcslen(ParameterName)*sizeof(WCHAR))
|
||
);
|
||
|
||
return Status;
|
||
}
|
||
|
||
|
||
/*-------------------------------
|
||
|
||
This set of routines implements the network provider order in the wrapper.
|
||
The way that this works is somewhat complicated. First, we go to the registry
|
||
to get the provider order; it is stored at key=PROVIDERORDER_REGISTRY_KEY and
|
||
value=L"ProviderOrder". This is a list of service providers whereas what we need
|
||
are the device names. So, for each ServiceProverName, we go to the registry to
|
||
get the device name at key=SERVICE_REGISTRY_KEY, subkey=ServiceProverName,
|
||
subsubkey=NETWORK_PROVIDER_SUBKEY, and value=L"Devicename".
|
||
|
||
We build a linked list of these guys. Later when a minirdr registers, we look
|
||
on this list for the corresponding device name and that gives us the priority.
|
||
|
||
simple? i think NOT.
|
||
|
||
|
||
----------------------------------*/
|
||
|
||
#ifndef MONOLITHIC_MINIRDR
|
||
|
||
NTSTATUS
|
||
RxAccrueProviderFromServiceName (
|
||
HANDLE ServicesHandle,
|
||
PUNICODE_STRING ServiceName,
|
||
ULONG Priority,
|
||
PWCHAR ProviderInfoNameBuffer,
|
||
ULONG ProviderInfoNameBufferLength
|
||
);
|
||
|
||
NTSTATUS
|
||
RxConstructProviderOrder (
|
||
void
|
||
);
|
||
|
||
VOID
|
||
RxDestructProviderOrder (
|
||
void
|
||
);
|
||
|
||
#ifdef ALLOC_PRAGMA
|
||
#pragma alloc_text(INIT, RxAccrueProviderFromServiceName)
|
||
#pragma alloc_text(INIT, RxConstructProviderOrder)
|
||
#pragma alloc_text(PAGE, RxDestructProviderOrder)
|
||
#endif
|
||
|
||
|
||
#define PROVIDERORDER_REGISTRY_KEY L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\NetworkProvider\\Order"
|
||
#define SERVICE_REGISTRY_KEY L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"
|
||
#define NETWORK_PROVIDER_SUBKEY L"\\networkprovider"
|
||
|
||
|
||
typedef struct _RX_UNC_PROVIDER_HEADER {
|
||
union {
|
||
LIST_ENTRY;
|
||
LIST_ENTRY Links;
|
||
};
|
||
ULONG Priority;
|
||
union {
|
||
UNICODE_STRING;
|
||
UNICODE_STRING DeviceName;
|
||
};
|
||
} RX_UNC_PROVIDER_HEADER;
|
||
|
||
typedef struct _RX_UNC_PROVIDER {
|
||
RX_UNC_PROVIDER_HEADER;
|
||
KEY_VALUE_PARTIAL_INFORMATION Info;
|
||
} RX_UNC_PROVIDER, *PRX_UNC_PROVIDER;
|
||
|
||
LIST_ENTRY RxUncProviders;
|
||
|
||
ULONG
|
||
RxGetNetworkProviderPriority(
|
||
IN PUNICODE_STRING DeviceName
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is called at minirdr registration time to find out the priority
|
||
of the provider with the given DeviceName. It simply looks it up on a list.
|
||
|
||
Arguments:
|
||
|
||
DeviceName - name of the device whose priority is to be found
|
||
|
||
Return Value:
|
||
|
||
the network provider priority that the MUP will use.
|
||
|
||
--*/
|
||
{
|
||
PLIST_ENTRY Entry;
|
||
|
||
PAGED_CODE();
|
||
|
||
RxLog(("FindUncProvider %wZ \n",DeviceName));
|
||
RxWmiLog(LOG,
|
||
RxGetNetworkProviderPriority,
|
||
LOGUSTR(*DeviceName));
|
||
|
||
for (Entry = RxUncProviders.Flink;
|
||
Entry != &RxUncProviders;
|
||
) {
|
||
|
||
PRX_UNC_PROVIDER UncProvider = (PRX_UNC_PROVIDER)Entry;
|
||
Entry = Entry->Flink;
|
||
if ( RtlEqualUnicodeString( DeviceName, &UncProvider->DeviceName, TRUE )) {
|
||
return(UncProvider->Priority);
|
||
}
|
||
|
||
}
|
||
|
||
// no corresponding entry was found
|
||
|
||
return(0x7effffff); //got this constant from the MUP........
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
RxAccrueProviderFromServiceName (
|
||
HANDLE ServicesHandle,
|
||
PUNICODE_STRING ServiceName,
|
||
ULONG Priority,
|
||
PWCHAR ProviderInfoNameBuffer,
|
||
ULONG ProviderInfoNameBufferLength
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine has the responsibility to look up the device name corresponding
|
||
to a particular provider name; if successful, the device name and the corresponding
|
||
priority are recorded on the UncProvider List.
|
||
|
||
Arguments:
|
||
|
||
HANDLE ServicesHandle - a handle to the services root in the registry
|
||
PUNICODE_STRING ServiceName - the name of the service relative to the servicehandle
|
||
ULONG Priority, - the priority of this provider
|
||
PWCHAR ProviderInfoNameBuffer, - a buffer that can be used to accrue the subkey name
|
||
ULONG ProviderInfoNameBufferLength - and the length
|
||
|
||
Return Value:
|
||
|
||
STATUS_SUCCESS if everything worked elsewise an error status.
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS Status;
|
||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||
UNICODE_STRING ProviderInfoName,ProviderInfoKey,ParameterDeviceName;
|
||
HANDLE NetworkProviderInfoHandle = INVALID_HANDLE_VALUE;
|
||
KEY_VALUE_PARTIAL_INFORMATION InitialValuePartialInformation;
|
||
ULONG DummyBytesRead,ProviderLength;
|
||
PRX_UNC_PROVIDER UncProvider = NULL;
|
||
|
||
PAGED_CODE();
|
||
|
||
RxLog(("SvcNm %wZ",ServiceName));
|
||
RxWmiLog(LOG,
|
||
RxAccrueProviderFromServiceName_1,
|
||
LOGUSTR(*ServiceName));
|
||
//
|
||
// Form the correct keyname using the bufferspace provided
|
||
|
||
ProviderInfoName.Buffer = ProviderInfoNameBuffer;
|
||
ProviderInfoName.Length = 0;
|
||
ProviderInfoName.MaximumLength = (USHORT)ProviderInfoNameBufferLength;
|
||
|
||
Status = RtlAppendUnicodeStringToString(&ProviderInfoName,ServiceName);
|
||
if (Status != STATUS_SUCCESS) {
|
||
DbgPrint("Could append1: %08lx %wZ\n",Status,&ProviderInfoName);
|
||
//RxAbbreviatedWriteLogEntry(Status);
|
||
goto FINALLY;
|
||
}
|
||
RtlInitUnicodeString(&ProviderInfoKey, NETWORK_PROVIDER_SUBKEY);
|
||
Status = RtlAppendUnicodeStringToString(&ProviderInfoName,&ProviderInfoKey);
|
||
if (Status != STATUS_SUCCESS) {
|
||
DbgPrint("Could append2: %08lx %wZ\n",Status,&ProviderInfoName);
|
||
RxAbbreviatedWriteLogEntry(Status);
|
||
goto FINALLY;
|
||
}
|
||
|
||
//
|
||
// Open the key in preparation for reeading the devicename value
|
||
|
||
//DbgPrint("RxAccrueProviderFromServiceName providerinfoname %wZ\n",&ProviderInfoName);
|
||
InitializeObjectAttributes(
|
||
&ObjectAttributes,
|
||
&ProviderInfoName, // name
|
||
OBJ_CASE_INSENSITIVE, // attributes
|
||
ServicesHandle, // root
|
||
NULL // security descriptor
|
||
);
|
||
|
||
Status = ZwOpenKey (&NetworkProviderInfoHandle, KEY_READ, &ObjectAttributes);
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
DbgPrint("NetWorkProviderInfoFailed: %08lx %wZ\n",Status,&ProviderInfoName);
|
||
RxAbbreviatedWriteLogEntry(Status);
|
||
goto FINALLY;
|
||
}
|
||
|
||
//
|
||
// Read the devicename. we do this in two steps. first, we do a partial read to find out
|
||
// how big the name really is. Then, we allocate a UncProviderEntry of the correctsize and make
|
||
// a second call to fill it in.
|
||
|
||
|
||
//DbgPrint("RxAccrueProviderFromServiceName ServiceName %wZ; worked\n",ServiceName);
|
||
RtlInitUnicodeString(&ParameterDeviceName, L"DeviceName");
|
||
|
||
Status = ZwQueryValueKey(NetworkProviderInfoHandle,
|
||
&ParameterDeviceName,
|
||
KeyValuePartialInformation,
|
||
&InitialValuePartialInformation,
|
||
sizeof(InitialValuePartialInformation),
|
||
&DummyBytesRead);
|
||
if (Status==STATUS_BUFFER_OVERFLOW) {
|
||
Status=STATUS_SUCCESS;
|
||
}
|
||
if (Status!=STATUS_SUCCESS) {
|
||
RxAbbreviatedWriteLogEntry(Status);
|
||
goto FINALLY;
|
||
}
|
||
//DbgPrint("RxAccrueProviderFromServiceName ServiceName %wZ; worked; devicenamesize=%08lx\n",
|
||
// ServiceName,InitialValuePartialInformation.DataLength);
|
||
|
||
ProviderLength = sizeof(RX_UNC_PROVIDER)+InitialValuePartialInformation.DataLength;
|
||
UncProvider = RxAllocatePoolWithTag(PagedPool | POOL_COLD_ALLOCATION ,ProviderLength,RX_MRX_POOLTAG);
|
||
if (UncProvider==NULL) {
|
||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||
DbgPrint("UncProviderAllocationFailed: %08lx %wZ\n",Status,&ProviderInfoName);
|
||
RxAbbreviatedWriteLogEntry(Status);
|
||
goto FINALLY;
|
||
}
|
||
|
||
Status = ZwQueryValueKey(NetworkProviderInfoHandle,
|
||
&ParameterDeviceName,
|
||
KeyValuePartialInformation,
|
||
&UncProvider->Info,
|
||
ProviderLength,
|
||
&DummyBytesRead);
|
||
if (Status!=STATUS_SUCCESS) {
|
||
RxAbbreviatedWriteLogEntry(Status);
|
||
goto FINALLY;
|
||
}
|
||
|
||
//
|
||
// Finish filling in the UncProviderEntry and link it in
|
||
|
||
UncProvider->Buffer = (PWCHAR)(&UncProvider->Info.Data[0]);
|
||
UncProvider->Length = (USHORT)(UncProvider->Info.DataLength-sizeof(WCHAR)); //dont include trailing NULL
|
||
UncProvider->MaximumLength = UncProvider->Length;
|
||
UncProvider->Priority = Priority;
|
||
|
||
InsertTailList(&RxUncProviders,&UncProvider->Links);
|
||
|
||
RxLog(("Dvc p=%lx Nm %wZ",UncProvider->Priority,&UncProvider->DeviceName));
|
||
RxWmiLog(LOG,
|
||
RxAccrueProviderFromServiceName_2,
|
||
LOGULONG(UncProvider->Priority)
|
||
LOGUSTR(UncProvider->DeviceName));
|
||
UncProvider = NULL;
|
||
|
||
FINALLY:
|
||
|
||
//
|
||
// if we obtained a handle to ...\\services\<sevicename>\providerinfo then close it
|
||
|
||
if (NetworkProviderInfoHandle!=INVALID_HANDLE_VALUE) ZwClose(NetworkProviderInfoHandle);
|
||
|
||
if (UncProvider != NULL) {
|
||
RxFreePool(UncProvider);
|
||
}
|
||
|
||
return Status;
|
||
}
|
||
|
||
NTSTATUS
|
||
RxConstructProviderOrder(
|
||
void
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine has the responsibility to build the list of network providers
|
||
that is used to look up provider priority at minirdr registration time. It does this
|
||
by first reading the providerorder string fron the registry; then for each provider
|
||
listed in the string, a helper routine is called to lookup the corresponding device
|
||
name and insert an entry on the provider list.
|
||
|
||
Arguments:
|
||
|
||
none.
|
||
|
||
Return Value:
|
||
|
||
STATUS_SUCCESS if everything worked elsewise an error status.
|
||
|
||
|
||
--*/
|
||
{
|
||
KEY_VALUE_PARTIAL_INFORMATION InitialValuePartialInformation;
|
||
UNICODE_STRING ProviderOrderValueName;
|
||
ULONG DummyBytesRead;
|
||
PBYTE ProviderOrderStringBuffer;
|
||
PBYTE ServiceNameStringBuffer = NULL;
|
||
ULONG ProviderOrderStringLength,ServiceNameStringLength,AllocationLength;
|
||
|
||
UNICODE_STRING UnicodeString;
|
||
UNICODE_STRING ProviderOrder;
|
||
PWCHAR ScanPtr,FinalScanPtr;
|
||
HANDLE NPOrderHandle = INVALID_HANDLE_VALUE;
|
||
HANDLE ServiceRootHandle = INVALID_HANDLE_VALUE;
|
||
NTSTATUS Status;
|
||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||
ULONG Priority = 0;
|
||
|
||
PAGED_CODE();
|
||
|
||
RxLog(("RxConstructProviderOrder"));
|
||
RxWmiLog(LOG,
|
||
RxConstructProviderOrder_1,
|
||
LOGULONG(Priority));
|
||
InitializeListHead(&RxUncProviders);
|
||
|
||
//
|
||
// Start by opening the service registry key. This is the root key of all services
|
||
// and is used for relative opens by the helper routine so that string manipulation
|
||
// is reduced.
|
||
|
||
RtlInitUnicodeString(&UnicodeString, SERVICE_REGISTRY_KEY);
|
||
|
||
InitializeObjectAttributes(
|
||
&ObjectAttributes,
|
||
&UnicodeString, // name
|
||
OBJ_CASE_INSENSITIVE, // attributes
|
||
NULL, // root
|
||
NULL // security descriptor
|
||
);
|
||
|
||
Status = ZwOpenKey (&ServiceRootHandle, KEY_READ, &ObjectAttributes);
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
DbgPrint("ServiceRootOpenFailed: %08lx %wZ\n",Status,&UnicodeString);
|
||
RxAbbreviatedWriteLogEntry(Status);
|
||
goto FINALLY;
|
||
}
|
||
|
||
//
|
||
// Now open up the key where we find the provider order string
|
||
|
||
RtlInitUnicodeString(&UnicodeString, PROVIDERORDER_REGISTRY_KEY);
|
||
|
||
InitializeObjectAttributes(
|
||
&ObjectAttributes,
|
||
&UnicodeString, // name
|
||
OBJ_CASE_INSENSITIVE, // attributes
|
||
NULL, // root
|
||
NULL // security descriptor
|
||
);
|
||
|
||
Status = ZwOpenKey (&NPOrderHandle, KEY_READ, &ObjectAttributes);
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
DbgPrint("NetProviderOpenFailed: %08lx %wZ\n",Status,&UnicodeString);
|
||
RxAbbreviatedWriteLogEntry(Status);
|
||
goto FINALLY;
|
||
}
|
||
|
||
//
|
||
//Find out how long the provider order string is
|
||
|
||
RtlInitUnicodeString(&ProviderOrderValueName, L"ProviderOrder");
|
||
|
||
Status = ZwQueryValueKey(NPOrderHandle,
|
||
&ProviderOrderValueName,
|
||
KeyValuePartialInformation,
|
||
&InitialValuePartialInformation,
|
||
sizeof(InitialValuePartialInformation),
|
||
&DummyBytesRead);
|
||
if (Status==STATUS_BUFFER_OVERFLOW) {
|
||
Status=STATUS_SUCCESS;
|
||
}
|
||
if (Status!=STATUS_SUCCESS) {
|
||
DbgPrint("ProviderOrderStringPartialInfoFailed: %08lx %wZ\n",Status,&ProviderOrderValueName);
|
||
RxAbbreviatedWriteLogEntry(Status);
|
||
goto FINALLY;
|
||
}
|
||
|
||
//
|
||
// allocate two buffers: one buffer will hold the provider string -- ProviderOrderStringBuffer.
|
||
// it has to be as long as the providerorder string plus enough extra for the registry
|
||
// structure used in the call. the second buffer is used to hold the servicename key--it has
|
||
// to be as long as any element of the provider string plus enough extra to hold the suffix
|
||
// NETWORK_PROVIDER_SUBKEY. in order to only parse the string once, we just allocate for a complete
|
||
// additional copy of the provider string. we actually combine these into a single allocation.
|
||
|
||
ProviderOrderStringLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + InitialValuePartialInformation.DataLength;
|
||
ProviderOrderStringLength = QuadAlign(ProviderOrderStringLength +2*sizeof(WCHAR)); //chars added below
|
||
|
||
ServiceNameStringLength = sizeof(NETWORK_PROVIDER_SUBKEY) + InitialValuePartialInformation.DataLength;
|
||
ServiceNameStringLength = QuadAlign(ServiceNameStringLength);
|
||
|
||
AllocationLength = ProviderOrderStringLength + ServiceNameStringLength;
|
||
RxLog(("prov string=%lx,alloc=%lx\n",
|
||
InitialValuePartialInformation.DataLength,
|
||
AllocationLength));
|
||
RxWmiLog(LOG,
|
||
RxConstructProviderOrder_2,
|
||
LOGULONG(InitialValuePartialInformation.DataLength)
|
||
LOGULONG(AllocationLength));
|
||
|
||
ServiceNameStringBuffer = RxAllocatePoolWithTag(PagedPool | POOL_COLD_ALLOCATION,AllocationLength,RX_MRX_POOLTAG);
|
||
if (ServiceNameStringBuffer==NULL) {
|
||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||
RxAbbreviatedWriteLogEntry(Status);
|
||
goto FINALLY;
|
||
}
|
||
ProviderOrderStringBuffer = ServiceNameStringBuffer+ServiceNameStringLength;
|
||
|
||
//
|
||
// now do the final read to get the providerorder string
|
||
|
||
RxGetStringRegistryParameter(NPOrderHandle,
|
||
L"ProviderOrder",
|
||
&ProviderOrder,
|
||
(PKEY_VALUE_PARTIAL_INFORMATION) ProviderOrderStringBuffer,
|
||
ProviderOrderStringLength,
|
||
FALSE
|
||
);
|
||
if (ProviderOrder.Buffer == NULL) {
|
||
Status = STATUS_UNSUCCESSFUL;
|
||
RxAbbreviatedWriteLogEntry(Status);
|
||
goto FINALLY;
|
||
}
|
||
|
||
//
|
||
// comma-terminate the string for easier living. then scan down the string
|
||
// looking for comma terminated entries. for each entry found, try to accrue
|
||
// it to the list
|
||
|
||
ProviderOrder.Buffer[ProviderOrder.Length/sizeof(WCHAR)] = L',';
|
||
|
||
ScanPtr = ProviderOrder.Buffer;
|
||
FinalScanPtr = ScanPtr+(ProviderOrder.Length/sizeof(WCHAR));
|
||
for (;;) {
|
||
|
||
UNICODE_STRING ServiceName;
|
||
|
||
// check for loop termination
|
||
|
||
if (ScanPtr >= FinalScanPtr) { break; }
|
||
if (*ScanPtr==L',') { ScanPtr++; continue; }
|
||
|
||
// parse for a servicename
|
||
|
||
ServiceName.Buffer = ScanPtr;
|
||
for (;*ScanPtr!=L',';ScanPtr++) {
|
||
//DbgPrint("Considering %c\n",*ScanPtr);
|
||
}
|
||
ASSERT(*ScanPtr==L',');
|
||
ServiceName.Length = (USHORT)(sizeof(WCHAR)*(ScanPtr - ServiceName.Buffer));
|
||
//DbgPrint("Length %08lx\n",ServiceName.Length);
|
||
//DbgPrint("ServiceName %wZ\n",&ServiceName);
|
||
|
||
// accrue it to the list
|
||
|
||
Priority++;
|
||
Status = RxAccrueProviderFromServiceName(ServiceRootHandle,
|
||
&ServiceName,
|
||
Priority,
|
||
(PWCHAR)ServiceNameStringBuffer,
|
||
ServiceNameStringLength );
|
||
if (Status == STATUS_INSUFFICIENT_RESOURCES) {
|
||
goto FINALLY; //a log entry has already been generated
|
||
} else {
|
||
Status = STATUS_SUCCESS;
|
||
}
|
||
}
|
||
|
||
FINALLY:
|
||
|
||
//
|
||
// give back anything that we got in this procedure
|
||
|
||
if (NPOrderHandle!=INVALID_HANDLE_VALUE) ZwClose(NPOrderHandle);
|
||
if (ServiceRootHandle!=INVALID_HANDLE_VALUE) ZwClose(ServiceRootHandle);
|
||
if (ServiceNameStringBuffer!=NULL) RxFreePool(ServiceNameStringBuffer);
|
||
|
||
//
|
||
// if things didn't work, then we won't start....so give back
|
||
// the stuff that we have
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
RxDestructProviderOrder();
|
||
}
|
||
return Status;
|
||
}
|
||
|
||
|
||
VOID
|
||
RxDestructProviderOrder(
|
||
void
|
||
)
|
||
{
|
||
PLIST_ENTRY Entry;
|
||
PAGED_CODE();
|
||
|
||
//DbgPrint("RxDestructProviderOrder \n");
|
||
for (Entry = RxUncProviders.Flink;
|
||
Entry != &RxUncProviders;
|
||
) {
|
||
PRX_UNC_PROVIDER UncProvider = (PRX_UNC_PROVIDER)Entry;
|
||
Entry = Entry->Flink;
|
||
//DbgPrint("RxDO UncP %wZ p=%x\n",&UncProvider->DeviceName,UncProvider->Priority);
|
||
RxFreePool(UncProvider);
|
||
}
|
||
return;
|
||
}
|
||
|
||
#else
|
||
ULONG
|
||
RxGetNetworkProviderPriority(
|
||
PUNICODE_STRING DeviceName
|
||
)
|
||
{
|
||
PAGED_CODE(); //DUPLICATE
|
||
|
||
return(1); //this number is irrelevant for monolithic
|
||
}
|
||
#endif //#ifndef MONOLITHIC_MINIRDR
|
||
|
||
NTSTATUS
|
||
RxInitializeRegistrationStructures(
|
||
void
|
||
)
|
||
{
|
||
NTSTATUS Status = STATUS_SUCCESS;
|
||
PAGED_CODE();
|
||
|
||
ExInitializeFastMutex(&RxData.MinirdrRegistrationMutex);
|
||
RxData.NumberOfMinirdrsRegistered = 0;
|
||
RxData.NumberOfMinirdrsStarted = 0;
|
||
InitializeListHead( &RxData.RegisteredMiniRdrs );
|
||
#ifndef MONOLITHIC_MINIRDR
|
||
Status = RxConstructProviderOrder();
|
||
#endif
|
||
return(Status);
|
||
}
|
||
|
||
VOID
|
||
RxUninitializeRegistrationStructures(
|
||
void
|
||
)
|
||
{
|
||
PAGED_CODE();
|
||
|
||
#ifndef MONOLITHIC_MINIRDR
|
||
RxDestructProviderOrder();
|
||
#endif
|
||
}
|
||
|
||
|
||
VOID
|
||
RxInitializeMinirdrDispatchTable(
|
||
IN PDRIVER_OBJECT DriverObject
|
||
)
|
||
{
|
||
PAGED_CODE();
|
||
|
||
#ifndef MONOLITHIC_MINIRDR
|
||
{ULONG i;
|
||
//finally, fill in the dispatch tables for normal guys.........
|
||
for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) {
|
||
DriverObject->MajorFunction[i] = RxData.DriverObject->MajorFunction[i];
|
||
}}
|
||
DriverObject->FastIoDispatch = RxData.DriverObject->FastIoDispatch;
|
||
#endif
|
||
}
|
||
|
||
|
||
VOID
|
||
NTAPI
|
||
__RxFillAndInstallFastIoDispatch(
|
||
IN PRDBSS_DEVICE_OBJECT RxDeviceObject,
|
||
IN OUT PFAST_IO_DISPATCH FastIoDispatch,
|
||
IN ULONG FastIoDispatchSize
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine fills out a fastiodispatch vector to be identical with
|
||
that normal one and installs it into the driver object associated with
|
||
the device object passed.
|
||
|
||
Arguments:
|
||
|
||
RxDeviceObject - the device object that is to have its driver's fastiodispatch changed
|
||
FastIoDispatch - the fastiodispatch table to fill in and use
|
||
FastIoDispatchSize - the size of the table passed
|
||
|
||
Return Value:
|
||
|
||
NONE
|
||
|
||
--*/
|
||
{
|
||
ULONG TableSize = min(FastIoDispatchSize,
|
||
RxFastIoDispatch.SizeOfFastIoDispatch);
|
||
PAGED_CODE();
|
||
|
||
#ifndef MONOLITHIC_MINIRDR
|
||
RtlCopyMemory(FastIoDispatch,&RxFastIoDispatch,TableSize);
|
||
FastIoDispatch->SizeOfFastIoDispatch = TableSize;
|
||
RxDeviceObject->DriverObject->FastIoDispatch = FastIoDispatch;
|
||
return;
|
||
#endif
|
||
}
|
||
|
||
VOID
|
||
RxReadRegistryParameters(
|
||
void
|
||
)
|
||
{
|
||
ULONG Storage[16];
|
||
UNICODE_STRING UnicodeString;
|
||
HANDLE ParametersHandle;
|
||
NTSTATUS Status;
|
||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||
UNICODE_STRING WorkStationParametersRegistryKeyName;
|
||
PKEY_VALUE_PARTIAL_INFORMATION Value = (PKEY_VALUE_PARTIAL_INFORMATION)Storage;
|
||
ULONG ValueSize;
|
||
ULONG BytesRead;
|
||
|
||
PAGED_CODE(); //INIT
|
||
|
||
RtlInitUnicodeString(&WorkStationParametersRegistryKeyName,
|
||
LANMAN_WORKSTATION_PARAMETERS);
|
||
|
||
ValueSize = sizeof(Storage);
|
||
|
||
InitializeObjectAttributes(
|
||
&ObjectAttributes,
|
||
&WorkStationParametersRegistryKeyName, // name
|
||
OBJ_CASE_INSENSITIVE, // attributes
|
||
NULL, // root
|
||
NULL // security descriptor
|
||
);
|
||
|
||
Status = ZwOpenKey (&ParametersHandle, KEY_READ, &ObjectAttributes);
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
|
||
//RxLogFailure (
|
||
// RxFileSystemDeviceObject,
|
||
// NULL,
|
||
// EVENT_RDR_CANT_READ_REGISTRY,
|
||
// Status);
|
||
return;
|
||
}
|
||
|
||
RtlInitUnicodeString(&UnicodeString, L"DisableByteRangeLockingOnReadOnlyFiles");
|
||
|
||
Status = ZwQueryValueKey(ParametersHandle,
|
||
&UnicodeString,
|
||
KeyValuePartialInformation,
|
||
Value,
|
||
ValueSize,
|
||
&BytesRead);
|
||
|
||
if (NT_SUCCESS(Status)) {
|
||
if (Value->Type == REG_DWORD) {
|
||
PULONG ConfigValue = (PULONG)&Value->Data[0];
|
||
DisableByteRangeLockingOnReadOnlyFiles =
|
||
(BOOLEAN) (*((PULONG)ConfigValue) != 0);
|
||
}
|
||
}
|
||
|
||
ZwClose(ParametersHandle);
|
||
}
|
||
|