📄 init.c
字号:
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;
MRxSmbDispatch.MRxLowIOSubmit[LOWIO_OP_NOTIFY_CHANGE_DIRECTORY] = MRxSmbNotifyChangeDirectory;
// Miscellanous
MRxSmbDispatch.MRxCompleteBufferingStateChangeRequest = MRxSmbCompleteBufferingStateChangeRequest;
// initialize the paging file list
InitializeListHead(&MRxSmbPagingFilesSrvOpenList);
// now callout to initialize other tables
SmbPseInitializeTables();
return(STATUS_SUCCESS);
}
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();
CurrentState = (MRXSMB_STATE)
InterlockedCompareExchange(
(PLONG)&MRxSmbState,
MRXSMB_STARTED,
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)) {
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 (NT_SUCCESS(Status)) {
Status = MRxSmbRegisterForPnpNotifications();
} 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);
}
}
} 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();
// Tear down the registration for notifications
MRxSmbDeregisterForPnpNotifications();
// tear down the recurrent services
MRxSmbTearDownRecurrentServices();
SmbMrxFinalizeStufferFacilities();
MRxSmbUninitializeSecurity();
// Tear down the connection engine database
SmbCeDbTearDown();
PoUnregisterSystemState(
MRxSmbPoRegistrationState);
if (s_pNegotiateSmb != NULL) {
RxFreePool(s_pNegotiateSmb - TRANSPORT_HEADER_SIZE);
s_pNegotiateSmb = 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();
if (MRxSmbSecurityInitialized)
return STATUS_SUCCESS;
if ( NULL == InitSecurityInterfaceW() ) {
ASSERT(FALSE);
Status = STATUS_INVALID_PARAMETER;
} else {
MRxSmbSecurityInitialized = TRUE;
Status = STATUS_SUCCESS;
}
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;
}
#define SMBMRX_CONFIG_COMPUTER_NAME \
L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\ComputerName\\ActiveComputerName"
#define COMPUTERNAME L"ComputerName"
#define SMBMRX_CONFIG_TRANSPORTS \
L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\LanmanWorkStation\\Linkage"
#define TRANSPORT_BINDINGS L"Bind"
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();
// 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.
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 = InitialPartialInformationValue.DataLength;
if (0) {
DbgPrint("SizeofBindingInfo=%08lx %08lx\n",
AllocationLength,
InitialPartialInformationValue.DataLength);
}
__assume_bound( AllocationLength );
if (AllocationLength > 0xFFFF) {
//
// Don't allow registry value to consume too much memory
//
return STATUS_INSUFFICIENT_RESOURCES;
}
AllocationLength += sizeof(KEY_VALUE_PARTIAL_INFORMATION);
//RtlInitUnicodeString(&UnicodeString, TRANSPORT_BINDINGS);
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"));
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);
RtlInitUnicodeString(&UnicodeString, SMBMRX_CONFIG_COMPUTER_NAME);
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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -