mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
849 lines
22 KiB
849 lines
22 KiB
/*++
|
|
|
|
Copyright (c) 1989 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
init.c
|
|
|
|
Abstract:
|
|
|
|
This module contains the initialization code of the NT redirector
|
|
File System Driver (FSD) and File System Process (FSP).
|
|
|
|
|
|
Author:
|
|
|
|
Larry Osterman (larryo) 24-May-1990
|
|
|
|
Environment:
|
|
|
|
Kernel mode, FSD, and FSP
|
|
|
|
Revision History:
|
|
|
|
30-May-1990 LarryO
|
|
|
|
Created
|
|
|
|
--*/
|
|
|
|
//
|
|
// Include modules
|
|
//
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
|
|
NTSTATUS
|
|
DriverEntry(
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PUNICODE_STRING RegistryPath
|
|
);
|
|
|
|
VOID
|
|
RdrUnload(
|
|
IN PDRIVER_OBJECT DriverObject
|
|
);
|
|
|
|
VOID
|
|
RdrReadRedirectorConfiguration(
|
|
PUNICODE_STRING RegistryPath
|
|
);
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(PAGE, DriverEntry, RdrReadRedirectorConfiguration)
|
|
#pragma alloc_text(PAGE, RdrUnload)
|
|
#endif
|
|
|
|
|
|
NTSTATUS
|
|
DriverEntry(
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PUNICODE_STRING RegistryPath
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the initialization routine for the file system. It is invoked once
|
|
when the driver is loaded into the system. Its job is to initialize all
|
|
the structures which will be used by the FSD and the FSP. It also creates
|
|
the process from which all of the file system threads will be executed. It
|
|
then registers the file system with the I/O system as a valid file system
|
|
resident in the system.
|
|
|
|
Arguments:
|
|
|
|
DriverObject - Pointer to driver object created by the system.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
|
|
PDEVICE_OBJECT DeviceObject;
|
|
|
|
PAGED_CODE();
|
|
|
|
#if MEMPRINT
|
|
MemPrintInitialize();
|
|
#endif
|
|
|
|
//
|
|
// Create the device object for this file system.
|
|
//
|
|
|
|
RtlInitUnicodeString( &RdrNameString, RdrName );
|
|
|
|
dprintf(DPRT_INIT, ("Creating device %wZ\n", &RdrNameString));
|
|
|
|
dprintf(DPRT_INIT, ("DriverObject at %08lx\n", DriverObject));
|
|
|
|
Status = IoCreateDevice( DriverObject,
|
|
sizeof(FS_DEVICE_OBJECT) - sizeof(DEVICE_OBJECT),
|
|
&RdrNameString,
|
|
FILE_DEVICE_NETWORK_FILE_SYSTEM,
|
|
FILE_REMOTE_DEVICE,
|
|
FALSE,
|
|
&DeviceObject );
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
InternalError(("Unable to create redirector device"));
|
|
RdrWriteErrorLogEntry(
|
|
NULL,
|
|
IO_ERR_INSUFFICIENT_RESOURCES,
|
|
EVENT_RDR_CANT_CREATE_DEVICE,
|
|
Status,
|
|
NULL,
|
|
0
|
|
);
|
|
return Status;
|
|
}
|
|
|
|
dprintf(DPRT_INIT, ("Device created at %08lx\n", DeviceObject));
|
|
|
|
#ifdef _PNP_POWER_
|
|
//
|
|
// This driver doesn't talk directly to a device, and isn't (at
|
|
// least right now) otherwise concerned about power management.
|
|
//
|
|
|
|
DeviceObject->DeviceObjectExtension->PowerControlNeeded = FALSE;
|
|
#endif
|
|
|
|
ExInitializeResource( &RdrDataResource );
|
|
|
|
//
|
|
// Initialize the statistics package.
|
|
//
|
|
|
|
KeInitializeSpinLock(&RdrStatisticsSpinLock);
|
|
|
|
//
|
|
// Save the driver object address for this file system driver.
|
|
//
|
|
|
|
RdrDriverObject = DriverObject;
|
|
|
|
//
|
|
// Save the device object address for this file system driver.
|
|
//
|
|
|
|
RdrDeviceObject = (PFS_DEVICE_OBJECT )DeviceObject;
|
|
|
|
//
|
|
// Initialize a global string that points to the name of the PIPE device.
|
|
//
|
|
|
|
RtlInitUnicodeString(&RdrPipeText, RdrPipeName);
|
|
|
|
//
|
|
// Initialize a global string that points to the name of the IPC device.
|
|
//
|
|
|
|
RtlInitUnicodeString(&RdrIpcText, RdrIpcName);
|
|
|
|
//
|
|
// Initialize a global string that points to the name of the MAILSLOT device.
|
|
//
|
|
|
|
RtlInitUnicodeString(&RdrMailslotText, RdrMailslotName);
|
|
|
|
//
|
|
// Initialize the name of the DATA alternate data stream.
|
|
//
|
|
|
|
RtlInitUnicodeString(&RdrDataText, RdrDataName);
|
|
|
|
//
|
|
// Initialize the discardable code functions before doing anything else.
|
|
//
|
|
|
|
RdrInitializeDiscardableCode();
|
|
|
|
RdrReadRedirectorConfiguration(RegistryPath);
|
|
|
|
dprintf(DPRT_INIT, ("Stacksize was %d, is %d\n",DeviceObject->StackSize,RdrStackSize));
|
|
DeviceObject->StackSize=(CHAR)RdrStackSize;
|
|
|
|
//
|
|
// Initialize the connection package
|
|
//
|
|
|
|
RdrpInitializeConnectPackage();
|
|
|
|
//
|
|
// Initialize the directory package
|
|
//
|
|
|
|
RdrInitializeDir();
|
|
|
|
//
|
|
// Initialize the Named Pipe package
|
|
//
|
|
|
|
RdrInitializeNp();
|
|
|
|
//
|
|
// Initialize the FCB package
|
|
//
|
|
|
|
RdrpInitializeFcb();
|
|
|
|
//
|
|
// Initialize the TDI package
|
|
//
|
|
|
|
RdrpInitializeTdi();
|
|
|
|
//
|
|
// Initialze the backpack package.
|
|
//
|
|
|
|
RdrpInitializeBackPack();
|
|
|
|
//
|
|
// Initialize the lock tracking package.
|
|
//
|
|
|
|
RdrpInitializeLockHead();
|
|
|
|
//
|
|
// Initialize the redirector interface to the executive work queue
|
|
// routines.
|
|
//
|
|
|
|
RdrpInitializeWorkQueue();
|
|
|
|
RdrpInitializeSmbBuffer();
|
|
|
|
if (!NT_SUCCESS(Status = RdrpInitializeFsp())) {
|
|
return Status;
|
|
}
|
|
|
|
DriverObject->DriverUnload = RdrUnload;
|
|
|
|
//
|
|
// This must be called exactly once
|
|
//
|
|
|
|
SeEnableAccessToExports();
|
|
|
|
BowserDriverEntry(DriverObject, RegistryPath);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
VOID
|
|
RdrUnload(
|
|
IN PDRIVER_OBJECT DriverObject
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the unload routine for the redirector filesystem.
|
|
|
|
Arguments:
|
|
|
|
DriverObject - pointer to the driver object for the redirector
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
PAGED_CODE();
|
|
|
|
BowserUnload(DriverObject);
|
|
|
|
if (RdrOperatingSystem.Buffer != NULL) {
|
|
RtlFreeUnicodeString(&RdrOperatingSystem);
|
|
}
|
|
|
|
if (RdrLanmanType.Buffer != NULL) {
|
|
RtlFreeUnicodeString(&RdrLanmanType);
|
|
}
|
|
|
|
//
|
|
// Scavenge the server entries
|
|
//
|
|
|
|
RdrScavengeServerEntries();
|
|
|
|
RdrpUninitializeConnectPackage();
|
|
|
|
RdrpUninitializeDir();
|
|
|
|
RdrpUninitializeNp();
|
|
|
|
RdrpUninitializeFcb();
|
|
|
|
RdrpUninitializeTdi();
|
|
|
|
RdrpUninitializeBackPack();
|
|
|
|
RdrpUninitializeLockHead();
|
|
|
|
RdrUnloadSecurity();
|
|
|
|
//
|
|
// Get rid of the redirectors SMB buffer pool.
|
|
//
|
|
|
|
RdrpUninitializeSmbBuffer();
|
|
|
|
SmbTraceTerminate(SMBTRACE_REDIRECTOR);
|
|
|
|
RdrpUninitializeFsp();
|
|
|
|
ExDeleteResource(&RdrDataResource);
|
|
|
|
RdrUninitializeDiscardableCode();
|
|
|
|
IoDeleteDevice((PDEVICE_OBJECT)RdrDeviceObject);
|
|
|
|
#ifdef RDR_PNP_POWER
|
|
if( RdrTransportBindingList != NULL ) {
|
|
FREE_POOL( RdrTransportBindingList );
|
|
RdrTransportBindingList = NULL;
|
|
}
|
|
#endif
|
|
|
|
#if RDRPOOLDBG
|
|
//
|
|
// If we're tracing pool, make sure we've gotten rid of everything.
|
|
//
|
|
|
|
ASSERT (CurrentAllocationCount == 0);
|
|
|
|
ASSERT (CurrentAllocationSize == 0);
|
|
#endif
|
|
|
|
//
|
|
// July 16, 1996 (3 days before NT 4.0 code freeze)
|
|
//
|
|
// Stopping and unloading the redir is a two part process. Stopping
|
|
// happens in StopRedirector, and involves sending disconnect SMBs to
|
|
// any connected servers. It might happen that the last disconnect we
|
|
// send completes, which unblocks the StopRedirector thread, which
|
|
// then calls RdrUnload, all *before* the final ret instruction in the
|
|
// RdrCompleteSend that unblocked the StopRedirector thread executes.
|
|
// In that case, the system bugchecks.
|
|
//
|
|
// This was seen during setup, when someone tries to join a domain, fails
|
|
// and hits the back key twice (which shuts down all networking).
|
|
//
|
|
|
|
{
|
|
LARGE_INTEGER delay;
|
|
delay.QuadPart = -10*1000*100; // 100 millisecond
|
|
|
|
KeDelayExecutionThread( KernelMode, FALSE, &delay );
|
|
}
|
|
|
|
}
|
|
|
|
|
|
VOID
|
|
RdrReadRedirectorConfiguration(
|
|
PUNICODE_STRING RegistryPath
|
|
)
|
|
{
|
|
ULONG Storage[256];
|
|
UNICODE_STRING UnicodeString;
|
|
HANDLE VersionHandle;
|
|
HANDLE RedirConfigHandle;
|
|
HANDLE ParametersHandle;
|
|
NTSTATUS Status;
|
|
ULONG BytesRead;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
PREDIR_CONFIG_INFO ConfigEntry;
|
|
PKEY_VALUE_FULL_INFORMATION Value = (PKEY_VALUE_FULL_INFORMATION)Storage;
|
|
|
|
PAGED_CODE();
|
|
|
|
RtlInitUnicodeString(&RdrOperatingSystem, NULL);
|
|
|
|
RtlInitUnicodeString(&RdrLanmanType, NULL);
|
|
|
|
|
|
RtlInitUnicodeString(&UnicodeString, RDR_CONFIG_CURRENT_WINDOWS_VERSION);
|
|
|
|
InitializeObjectAttributes(
|
|
&ObjectAttributes,
|
|
&UnicodeString, // name
|
|
OBJ_CASE_INSENSITIVE, // attributes
|
|
NULL, // root
|
|
NULL // security descriptor
|
|
);
|
|
|
|
Status = ZwOpenKey (&VersionHandle, KEY_READ, &ObjectAttributes);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
RdrWriteErrorLogEntry (
|
|
NULL,
|
|
IO_ERR_CONFIGURATION_ERROR,
|
|
EVENT_RDR_CANT_READ_REGISTRY,
|
|
Status,
|
|
NULL,
|
|
0
|
|
);
|
|
|
|
return;
|
|
}
|
|
|
|
RtlInitUnicodeString(&UnicodeString, RDR_CONFIG_OPERATING_SYSTEM);
|
|
|
|
Status = ZwQueryValueKey(VersionHandle,
|
|
&UnicodeString,
|
|
KeyValueFullInformation,
|
|
Value,
|
|
sizeof(Storage),
|
|
&BytesRead);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
RdrWriteErrorLogEntry (
|
|
NULL,
|
|
IO_ERR_CONFIGURATION_ERROR,
|
|
EVENT_RDR_CANT_READ_REGISTRY,
|
|
Status,
|
|
NULL,
|
|
0
|
|
);
|
|
ZwClose(VersionHandle);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ASSERT (Value->Type == REG_SZ);
|
|
|
|
if (Value->DataLength != 0) {
|
|
|
|
RdrOperatingSystem.MaximumLength =
|
|
RdrOperatingSystem.Length = (USHORT)Value->DataLength+
|
|
sizeof(RDR_CONFIG_OPERATING_SYSTEM_NAME)-sizeof(WCHAR);
|
|
|
|
RdrOperatingSystem.Buffer = ExAllocatePool(PagedPool, RdrOperatingSystem.Length);
|
|
|
|
if (RdrOperatingSystem.Buffer == NULL) {
|
|
|
|
RdrWriteErrorLogEntry (
|
|
NULL,
|
|
IO_ERR_CONFIGURATION_ERROR,
|
|
EVENT_RDR_CANT_READ_REGISTRY,
|
|
Status,
|
|
NULL,
|
|
0
|
|
);
|
|
|
|
ZwClose(VersionHandle);
|
|
|
|
return;
|
|
}
|
|
|
|
RtlCopyMemory(RdrOperatingSystem.Buffer, RDR_CONFIG_OPERATING_SYSTEM_NAME, sizeof(RDR_CONFIG_OPERATING_SYSTEM_NAME));
|
|
|
|
RtlCopyMemory(RdrOperatingSystem.Buffer+(sizeof(RDR_CONFIG_OPERATING_SYSTEM_NAME)/sizeof(WCHAR))-1, (PCHAR)Value+Value->DataOffset, Value->DataLength);
|
|
|
|
} else {
|
|
RdrWriteErrorLogEntry (
|
|
NULL,
|
|
IO_ERR_CONFIGURATION_ERROR,
|
|
EVENT_RDR_CANT_READ_REGISTRY,
|
|
STATUS_INVALID_PARAMETER,
|
|
RDR_CONFIG_OPERATING_SYSTEM,
|
|
sizeof(RDR_CONFIG_OPERATING_SYSTEM)
|
|
);
|
|
ZwClose(VersionHandle);
|
|
}
|
|
|
|
RtlInitUnicodeString(&UnicodeString, RDR_CONFIG_OPERATING_SYSTEM_VERSION);
|
|
|
|
Status = ZwQueryValueKey(VersionHandle,
|
|
&UnicodeString,
|
|
KeyValueFullInformation,
|
|
Value,
|
|
sizeof(Storage),
|
|
&BytesRead);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
RdrWriteErrorLogEntry (
|
|
NULL,
|
|
IO_ERR_CONFIGURATION_ERROR,
|
|
EVENT_RDR_CANT_READ_REGISTRY,
|
|
STATUS_INSUFFICIENT_RESOURCES,
|
|
NULL,
|
|
0
|
|
);
|
|
ZwClose(VersionHandle);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ASSERT (Value->Type == REG_SZ);
|
|
|
|
if (Value->DataLength != 0) {
|
|
|
|
RdrLanmanType.MaximumLength =
|
|
RdrLanmanType.Length = (USHORT)Value->DataLength+sizeof(RDR_CONFIG_OPERATING_SYSTEM_NAME)-sizeof(WCHAR);
|
|
|
|
RdrLanmanType.Buffer = ExAllocatePool(PagedPool, RdrLanmanType.Length);
|
|
|
|
if (RdrLanmanType.Buffer == NULL) {
|
|
|
|
RdrWriteErrorLogEntry (
|
|
NULL,
|
|
IO_ERR_CONFIGURATION_ERROR,
|
|
EVENT_RDR_CANT_READ_REGISTRY,
|
|
STATUS_INSUFFICIENT_RESOURCES,
|
|
NULL,
|
|
0
|
|
);
|
|
|
|
ZwClose(VersionHandle);
|
|
|
|
return;
|
|
}
|
|
|
|
RtlCopyMemory(RdrLanmanType.Buffer, RDR_CONFIG_OPERATING_SYSTEM_NAME, sizeof(RDR_CONFIG_OPERATING_SYSTEM_NAME));
|
|
|
|
RtlCopyMemory(RdrLanmanType.Buffer+(sizeof(RDR_CONFIG_OPERATING_SYSTEM_NAME)/sizeof(WCHAR))-1, (PCHAR)Value+Value->DataOffset, Value->DataLength);
|
|
|
|
} else {
|
|
RdrWriteErrorLogEntry (
|
|
NULL,
|
|
IO_ERR_CONFIGURATION_ERROR,
|
|
EVENT_RDR_CANT_READ_REGISTRY,
|
|
STATUS_INVALID_PARAMETER,
|
|
RDR_CONFIG_OPERATING_SYSTEM_VERSION,
|
|
sizeof(RDR_CONFIG_OPERATING_SYSTEM_VERSION)
|
|
);
|
|
|
|
}
|
|
|
|
ZwClose(VersionHandle);
|
|
|
|
InitializeObjectAttributes(
|
|
&ObjectAttributes,
|
|
RegistryPath, // name
|
|
OBJ_CASE_INSENSITIVE, // attributes
|
|
NULL, // root
|
|
NULL // security descriptor
|
|
);
|
|
|
|
Status = ZwOpenKey (&RedirConfigHandle, KEY_READ, &ObjectAttributes);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
RdrWriteErrorLogEntry (
|
|
NULL,
|
|
IO_ERR_CONFIGURATION_ERROR,
|
|
EVENT_RDR_CANT_READ_REGISTRY,
|
|
Status,
|
|
NULL,
|
|
0
|
|
);
|
|
|
|
return;
|
|
}
|
|
|
|
RtlInitUnicodeString(&UnicodeString, RDR_CONFIG_PARAMETERS);
|
|
|
|
InitializeObjectAttributes(
|
|
&ObjectAttributes,
|
|
&UnicodeString,
|
|
OBJ_CASE_INSENSITIVE,
|
|
RedirConfigHandle,
|
|
NULL
|
|
);
|
|
|
|
|
|
Status = ZwOpenKey (&ParametersHandle, KEY_READ, &ObjectAttributes);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
RdrWriteErrorLogEntry (
|
|
NULL,
|
|
IO_ERR_CONFIGURATION_ERROR,
|
|
EVENT_RDR_CANT_READ_REGISTRY,
|
|
Status,
|
|
NULL,
|
|
0
|
|
);
|
|
|
|
ZwClose(RedirConfigHandle);
|
|
|
|
return;
|
|
}
|
|
|
|
for (ConfigEntry = RdrConfigEntries;
|
|
ConfigEntry->ConfigParameterName != NULL;
|
|
ConfigEntry += 1) {
|
|
|
|
RtlInitUnicodeString(&UnicodeString, ConfigEntry->ConfigParameterName);
|
|
|
|
Status = ZwQueryValueKey(ParametersHandle,
|
|
&UnicodeString,
|
|
KeyValueFullInformation,
|
|
Value,
|
|
sizeof(Storage),
|
|
&BytesRead);
|
|
|
|
|
|
if (NT_SUCCESS(Status)) {
|
|
|
|
if (Value->DataLength != 0) {
|
|
|
|
if (ConfigEntry->ConfigValueType == REG_BOOLEAN) {
|
|
if (Value->Type != REG_DWORD ||
|
|
Value->DataLength != REG_BOOLEAN_SIZE) {
|
|
RdrWriteErrorLogEntry (
|
|
NULL,
|
|
IO_ERR_CONFIGURATION_ERROR,
|
|
EVENT_RDR_CANT_READ_REGISTRY,
|
|
STATUS_INVALID_PARAMETER,
|
|
ConfigEntry->ConfigParameterName,
|
|
(USHORT)(wcslen(ConfigEntry->ConfigParameterName)*sizeof(WCHAR))
|
|
);
|
|
|
|
} else {
|
|
ULONG ConfigValue = (ULONG)((PCHAR)Value)+Value->DataOffset;
|
|
|
|
*(PBOOLEAN)(ConfigEntry->ConfigValue) = (BOOLEAN)(*((PULONG)ConfigValue) != 0);
|
|
}
|
|
|
|
} else if (Value->Type != ConfigEntry->ConfigValueType ||
|
|
Value->DataLength != ConfigEntry->ConfigValueSize) {
|
|
|
|
RdrWriteErrorLogEntry (
|
|
NULL,
|
|
IO_ERR_CONFIGURATION_ERROR,
|
|
EVENT_RDR_CANT_READ_REGISTRY,
|
|
STATUS_INVALID_PARAMETER,
|
|
ConfigEntry->ConfigParameterName,
|
|
(USHORT)(wcslen(ConfigEntry->ConfigParameterName)*sizeof(WCHAR))
|
|
);
|
|
|
|
} else {
|
|
|
|
RtlCopyMemory(ConfigEntry->ConfigValue, ((PCHAR)Value)+Value->DataOffset, Value->DataLength);
|
|
}
|
|
} else {
|
|
RdrWriteErrorLogEntry (
|
|
NULL,
|
|
IO_ERR_CONFIGURATION_ERROR,
|
|
EVENT_RDR_CANT_READ_REGISTRY,
|
|
STATUS_INVALID_PARAMETER,
|
|
ConfigEntry->ConfigParameterName,
|
|
(USHORT)(wcslen(ConfigEntry->ConfigParameterName)*sizeof(WCHAR))
|
|
);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
#ifdef RDR_PNP_POWER
|
|
#define RDR_BINDING_PATH L"\\REGISTRY\\Machine\\System\\CurrentControlSet\\Services\\LanmanWorkstation\\Linkage"
|
|
|
|
//
|
|
// Read the binding list out of the registry, and store it away. This
|
|
// list is later used when PNP binding notifications arrive from TDI to
|
|
// see if it's a device we're interested in
|
|
//
|
|
RtlInitUnicodeString( &UnicodeString, RDR_BINDING_PATH );
|
|
|
|
InitializeObjectAttributes(
|
|
&ObjectAttributes,
|
|
&UnicodeString, // name
|
|
OBJ_CASE_INSENSITIVE, // attributes
|
|
NULL, // root
|
|
NULL // security descriptor
|
|
);
|
|
|
|
|
|
//
|
|
// This is written as do{}while(0) to allow 'break' to take us all of
|
|
// the way out. Avoids gotos and deep nesting.
|
|
//
|
|
do {
|
|
|
|
ULONG lengthNeeded;
|
|
PKEY_VALUE_FULL_INFORMATION infoBuffer = NULL;
|
|
HANDLE BindingHandle;
|
|
|
|
Status = ZwOpenKey( &BindingHandle, KEY_READ, &ObjectAttributes );
|
|
|
|
if( !NT_SUCCESS( Status ) ) {
|
|
break;
|
|
}
|
|
|
|
RtlInitUnicodeString( &UnicodeString, L"Bind" );
|
|
|
|
Status = ZwQueryValueKey( BindingHandle,
|
|
&UnicodeString,
|
|
KeyValueFullInformation,
|
|
NULL,
|
|
0,
|
|
&lengthNeeded );
|
|
|
|
if( Status != STATUS_BUFFER_TOO_SMALL || lengthNeeded == 0 ) {
|
|
ZwClose( BindingHandle );
|
|
break;
|
|
}
|
|
|
|
infoBuffer = ALLOCATE_POOL( PagedPool, lengthNeeded, POOL_PNP_DATA );
|
|
|
|
if( infoBuffer == NULL ) {
|
|
ZwClose( BindingHandle );
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
break;
|
|
}
|
|
|
|
Status = ZwQueryValueKey( BindingHandle,
|
|
&UnicodeString,
|
|
KeyValueFullInformation,
|
|
infoBuffer,
|
|
lengthNeeded,
|
|
&BytesRead );
|
|
|
|
ZwClose( BindingHandle );
|
|
|
|
if( !NT_SUCCESS( Status ) || infoBuffer->DataLength == 0 || infoBuffer->Type != REG_MULTI_SZ ) {
|
|
FREE_POOL( infoBuffer );
|
|
break;
|
|
}
|
|
|
|
RdrTransportBindingList = ALLOCATE_POOL( PagedPool, infoBuffer->DataLength, POOL_PNP_DATA );
|
|
|
|
if( RdrTransportBindingList == NULL ) {
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
FREE_POOL( infoBuffer );
|
|
break;
|
|
}
|
|
|
|
RtlCopyMemory( RdrTransportBindingList,
|
|
((PCHAR)infoBuffer) + infoBuffer->DataOffset,
|
|
infoBuffer->DataLength
|
|
);
|
|
|
|
FREE_POOL( infoBuffer );
|
|
|
|
} while( 0 );
|
|
|
|
if( RdrTransportBindingList == NULL ) {
|
|
|
|
RdrWriteErrorLogEntry ( NULL,
|
|
IO_ERR_CONFIGURATION_ERROR,
|
|
EVENT_RDR_CANT_READ_REGISTRY,
|
|
Status,
|
|
UnicodeString.Buffer,
|
|
UnicodeString.Length
|
|
);
|
|
}
|
|
|
|
#endif //def RDR_PNP_POWER
|
|
|
|
|
|
#if !defined(DISABLE_POPUP_ON_PRIMARY_TRANSPORT_FAILURE)
|
|
//
|
|
//
|
|
|
|
#define RDR_CONFIG_ALL_SERVERS L"\\REGISTRY\\Machine\\Software\\Microsoft\\LanmanWorkstation\\CurrentVersion"
|
|
|
|
RtlInitUnicodeString(&UnicodeString, RDR_CONFIG_ALL_SERVERS);
|
|
|
|
InitializeObjectAttributes(
|
|
&ObjectAttributes,
|
|
&UnicodeString, // name
|
|
OBJ_CASE_INSENSITIVE, // attributes
|
|
NULL, // root
|
|
NULL // security descriptor
|
|
);
|
|
|
|
Status = ZwOpenKey (&VersionHandle, KEY_READ, &ObjectAttributes);
|
|
|
|
if (NT_SUCCESS(Status)) {
|
|
RtlInitUnicodeString(&UnicodeString, L"ServersWithAllTransports");
|
|
|
|
Status = ZwQueryValueKey(VersionHandle,
|
|
&UnicodeString,
|
|
KeyValueFullInformation,
|
|
Value,
|
|
sizeof(Storage),
|
|
&BytesRead);
|
|
|
|
|
|
if (NT_SUCCESS(Status)) {
|
|
|
|
if (Value->DataLength != 0) {
|
|
if (Value->Type == REG_MULTI_SZ) {
|
|
RdrServersWithAllTransports = ALLOCATE_POOL(PagedPool, Value->DataLength, POOL_PRIMARYTRANSPORTSERVER);
|
|
|
|
if (RdrServersWithAllTransports == NULL) {
|
|
RdrWriteErrorLogEntry (
|
|
NULL,
|
|
IO_ERR_CONFIGURATION_ERROR,
|
|
EVENT_RDR_CANT_READ_REGISTRY,
|
|
STATUS_INSUFFICIENT_RESOURCES,
|
|
NULL,
|
|
0
|
|
);
|
|
|
|
} else {
|
|
RtlCopyMemory(RdrServersWithAllTransports, ((PCHAR)Value)+Value->DataOffset, Value->DataLength);
|
|
}
|
|
} else {
|
|
RdrWriteErrorLogEntry (
|
|
NULL,
|
|
IO_ERR_CONFIGURATION_ERROR,
|
|
EVENT_RDR_CANT_READ_REGISTRY,
|
|
STATUS_INVALID_PARAMETER,
|
|
ConfigEntry->ConfigParameterName,
|
|
(USHORT)(wcslen(ConfigEntry->ConfigParameterName)*sizeof(WCHAR))
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
ZwClose(VersionHandle);
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
ZwClose(ParametersHandle);
|
|
|
|
ZwClose(RedirConfigHandle);
|
|
|
|
}
|