📄 transprt.c
字号:
RxCeTearDownTransport(&pTransport->RxCeTransport);
if (AttachToSystemProcess) {
KeUnstackDetachProcess(&ApcState);
}
RxFreePool(pTransport);
}
} else {
Status = STATUS_INVALID_PARAMETER;
}
return Status;
}
HANDLE MRxSmbTdiNotificationHandle = NULL;
KEVENT TdiNetStartupCompletionEvent;
LONG TdiBindRequestsActive = 0;
BOOLEAN TdiPnpNetReadyEventReceived = FALSE;
// The TRANSPORT_BIND_CONTEXT contains the result of the priority determination
// as well as the name. The priority is used to order the transports in the order
// in which connection attempts will be made
typedef struct _TRANSPORT_BIND_CONTEXT_ {
ULONG Priority;
UNICODE_STRING TransportName;
} TRANSPORT_BIND_CONTEXT, *PTRANSPORT_BIND_CONTEXT;
VOID
SmbCeSignalNetReadyEvent()
/*++
Routine Description:
The routine signals the net ready event if all the bind requests
have been completed and if the net ready event has been received from TDI
Arguments:
--*/
{
BOOLEAN SignalNetReadyEvent = FALSE;
SmbCeAcquireSpinLock();
if (TdiPnpNetReadyEventReceived &&
TdiBindRequestsActive == 0) {
SignalNetReadyEvent = TRUE;
}
SmbCeReleaseSpinLock();
if (SignalNetReadyEvent) {
KeSetEvent(
&TdiNetStartupCompletionEvent,
IO_NETWORK_INCREMENT,
FALSE);
}
}
VOID
MRxSmbpBindTransportCallback(
IN PTRANSPORT_BIND_CONTEXT pTransportContext)
/*++
Routine Description:
TDI calls this routine whenever a transport creates a new device object.
Arguments:
TransportName - the name of the newly created device object
TransportBindings - the transport bindings ( multi sz)
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
PSMBCE_TRANSPORT pTransport;
PUNICODE_STRING pTransportName;
PAGED_CODE();
ASSERT(IoGetCurrentProcess() == RxGetRDBSSProcess());
pTransportName = &pTransportContext->TransportName;
RxDbgTrace( 0, Dbg, ("MrxSmbpBindTransportCallback, Transport Name = %wZ\n", pTransportName ));
pTransport = RxAllocatePoolWithTag(
NonPagedPool,
sizeof(SMBCE_TRANSPORT),
MRXSMB_TRANSPORT_POOLTAG);
if (pTransport != NULL) {
Status = RxCeBuildTransport(
&pTransport->RxCeTransport,
pTransportName,
0xffff);
if (Status == STATUS_SUCCESS) {
PRXCE_TRANSPORT_PROVIDER_INFO pProviderInfo;
pProviderInfo = pTransport->RxCeTransport.pProviderInfo;
if (!(pProviderInfo->ServiceFlags & TDI_SERVICE_CONNECTION_MODE) ||
!(pProviderInfo->ServiceFlags & TDI_SERVICE_ERROR_FREE_DELIVERY)) {
RxCeTearDownTransport(
&pTransport->RxCeTransport);
Status = STATUS_PROTOCOL_UNREACHABLE;
RxFreePool(pTransport);
}
}
} else {
Status = STATUS_INSUFFICIENT_RESOURCES;
}
if (Status == STATUS_SUCCESS) {
// The connection capabilities match the capabilities required by the
// SMB mini redirector. Attempt to register the local address with the
// transport and if successful update the local transport list to include
// this transport for future connection considerations.
OEM_STRING OemServerName;
CHAR TransportAddressBuffer[TDI_TRANSPORT_ADDRESS_LENGTH +
TDI_ADDRESS_LENGTH_NETBIOS];
PTRANSPORT_ADDRESS pTransportAddress = (PTRANSPORT_ADDRESS)TransportAddressBuffer;
PTDI_ADDRESS_NETBIOS pNetbiosAddress = (PTDI_ADDRESS_NETBIOS)pTransportAddress->Address[0].Address;
pTransportAddress->TAAddressCount = 1;
pTransportAddress->Address[0].AddressLength = TDI_ADDRESS_LENGTH_NETBIOS;
pTransportAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_NETBIOS;
pNetbiosAddress->NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_UNIQUE;
OemServerName.MaximumLength = NETBIOS_NAME_LEN;
OemServerName.Buffer = pNetbiosAddress->NetbiosName;
Status = RtlUpcaseUnicodeStringToOemString(
&OemServerName,
&SmbCeContext.ComputerName,
FALSE);
if (NT_SUCCESS(Status)) {
// Ensure that the name is always of the desired length by padding
// white space to the end.
RtlCopyMemory(
&OemServerName.Buffer[OemServerName.Length],
" ",
NETBIOS_NAME_LEN - OemServerName.Length);
OemServerName.Buffer[NETBIOS_NAME_LEN - 1] = '\0';
// Register the Transport address for this mini redirector with the connection
// engine.
Status = RxCeBuildAddress(
&pTransport->RxCeAddress,
&pTransport->RxCeTransport,
pTransportAddress,
&MRxSmbVctAddressEventHandler,
&SmbCeContext);
if (Status == STATUS_SUCCESS) {
RxDbgTrace( 0, Dbg, ("MRxSmbTransportUpdateHandler: Adding new transport\n"));
pTransport->Active = TRUE;
pTransport->Priority = pTransportContext->Priority;
pTransport->SwizzleCount = 0;
pTransport->ObjectCategory = SMB_SERVER_TRANSPORT_CATEGORY;
pTransport->ObjectType = SMBCEDB_OT_TRANSPORT;
pTransport->State = 0;
pTransport->Flags = 0;
SmbCeAddTransport(pTransport);
RxDbgTrace( 0, Dbg, ("MrxSmbpBindTransportCallback, Transport %wZ added\n", pTransportName ));
} else {
RxDbgTrace( 0, Dbg, ("MRxSmbTransportUpdateHandler: Address registration failed %lx\n",Status));
}
}
if (Status != STATUS_SUCCESS) {
RxDbgTrace( 0, Dbg, ("MrxSmbpBindTransportCallback, Transport %wZ unreachable 0x%x\n",
pTransportName, Status ));
RxCeTearDownTransport(
&pTransport->RxCeTransport);
Status = STATUS_PROTOCOL_UNREACHABLE;
RxFreePool(pTransport);
}
}
InterlockedDecrement(&TdiBindRequestsActive);
SmbCeSignalNetReadyEvent();
}
VOID
MRxSmbpBindTransportWorkerThreadRoutine(
IN PTRANSPORT_BIND_CONTEXT pTransportContext)
/*++
Routine Description:
The TDI callbacks always do not occur in the context of the FSP process.
Since there are a few TDi interfaces that accept handles we need to ensure
that such calls always gets funnelled back to the FSP.
Arguments:
pTransportContext - the transport binding context
--*/
{
PAGED_CODE();
MRxSmbpBindTransportCallback(pTransportContext);
RxFreePool(pTransportContext);
}
VOID
MRxSmbpUnbindTransportCallback(
PSMBCE_TRANSPORT pTransport)
/*++
Routine Description:
The Unbind callback routine which is always executed in the context of the
RDR process so that handles can be closed correctly
Arguments:
pTransport - the transport for which the PNP_OP_DEL was received
Notes:
On entry to this routine the appropriate transport must have been referenced
This routine will dereference it and invalidate the existing exchanges using
this transport.
--*/
{
PAGED_CODE();
// Remove this transport from the list of transports under consideration
// in the mini redirector.
SmbCeRemoveTransport(pTransport);
// Enumerate the servers and mark those servers utilizing this transport
// as having an invalid transport.
SmbCeHandleTransportInvalidation(pTransport);
// dereference the transport
SmbCeDereferenceTransport(pTransport);
}
VOID
MRxSmbpOverrideBindingPriority(
PUNICODE_STRING pTransportName,
PULONG pPriority
)
/*++
Routine Description:
This function obtains a overriding priority value from the registry for a given
transport.
The priority of a transport controls the order in which connections are accepted. It is
sometimes useful for a customer to control which transport is used first in the redirector.
The priority is usually determined by the order of the transports in the binding list. With
the new Connections UI model for network setup, it will no longer be possible to adjust
the order of the bindings in the binding list. Thus, another mechanism is needed when the
user wants to override the priority assigned to a given binding.
Arguments:
pTransportName - pointer to UNICODE_STRING descriptor for transport string, for example
"\Device\Netbt_tcpip_{guid}"
pPriority - pointer to LONG to receive new priority on success, otherwise not touched
Return Value:
None
--*/
{
WCHAR valueBuffer[128];
UNICODE_STRING path, value, key;
USHORT length,ulength;
OBJECT_ATTRIBUTES objectAttributes;
NTSTATUS status;
HANDLE parametersHandle;
ULONG temp;
PAGED_CODE();
// Validate input
if (pTransportName->Length == 0) {
return;
}
// Open parameters key
RtlInitUnicodeString( &path, SMBMRX_MINIRDR_PARAMETERS );
InitializeObjectAttributes(
&objectAttributes,
&path,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
status = ZwOpenKey (¶metersHandle, KEY_READ, &objectAttributes);
if (!NT_SUCCESS(status)) {
return;
}
// Construct value name = "BindingPriority" + transportname
// First, find the last slash. Then form the value from the prefix and
// the remainder of the transport name.
ulength = pTransportName->Length / sizeof(WCHAR);
for( length = ulength - 1; length != 0; length-- ) {
if (pTransportName->Buffer[length] == L'\\') {
break;
}
}
length++;
key.Buffer = pTransportName->Buffer + length;
key.Length = (ulength - length) * sizeof(WCHAR);
value.Buffer = valueBuffer;
value.MaximumLength = 128 * sizeof(WCHAR);
value.Length = 0;
RtlAppendUnicodeToString( &value, L"BindingPriority" );
RtlAppendUnicodeStringToString( &value, &key );
// Check if the value is present. If so, replace priority
// A value of zero is valid and indicates do not bind this one
status = MRxSmbGetUlongRegistryParameter(
parametersHandle,
value.Buffer,
(PULONG)&temp,
FALSE );
if (NT_SUCCESS(status)) {
*pPriority = temp;
}
ZwClose(parametersHandle);
}
VOID
MRxSmbPnPBindingHandler(
__in TDI_PNP_OPCODE PnPOpcode,
__in PUNICODE_STRING pTransportName,
__in PWSTR BindingList)
/*++
Routine Description:
The TDI callbacks routine for binding changes
Arguments:
PnPOpcode - the PNP op code
pTransportName - the transport name
BindingList - the binding order
--*/
{
ULONG Priority;
NTSTATUS Status;
PAGED_CODE();
switch (PnPOpcode) {
case TDI_PNP_OP_ADD:
{
BOOLEAN fBindToTransport = FALSE;
PWSTR pSmbMRxTransports;
UNICODE_STRING SmbMRxTransport;
Status = SmbCeGetConfigurationInformation();
if (Status != STATUS_SUCCESS) {
return;
}
pSmbMRxTransports = (PWSTR)SmbCeContext.Transports.Buffer;
Priority = 1;
while (*pSmbMRxTransports) {
SmbMRxTransport.Length = wcslen(pSmbMRxTransports) * sizeof(WCHAR);
if (SmbMRxTransport.Length == pTransportName->Length) {
SmbMRxTransport.MaximumLength = SmbMRxTransport.Length;
SmbMRxTransport.Buffer = pSmbMRxTransports;
if (RtlCompareUnicodeString(
&SmbMRxTransport,
pTransportName,
TRUE) == 0) {
fBindToTransport = TRUE;
break;
}
}
pSmbMRxTransports += (SmbMRxTransport.Length / sizeof(WCHAR) + 1);
Priority++;
}
// Provide a local registry means to alter binding priority
// if (fBindToTransport) {
// MRxSmbpOverrideBindingPriority( pTransportName, &Priority );
// fBindToTransport = (Priority != 0);
// }
if (fBindToTransport) {
InterlockedIncrement(&TdiBindRequestsActive);
if (IoGetCurrentProcess() == RxGetRDBSSProcess()) {
TRANSPORT_BIND_CONTEXT TransportContext;
TransportContext.Priority = Priority;
TransportContext.TransportName = *pTransportName;
MRxSmbpBindTransportCallback(&TransportContext);
} else {
PTRANSPORT_BIND_CONTEXT pNewTransportContext;
pNewTransportContext = RxAllocatePoolWithTag(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -