Windows NT 4.0 source code leak
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

/*++
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);
}