📄 transprt.c
字号:
PagedPool,
sizeof(TRANSPORT_BIND_CONTEXT) + pTransportName->Length,
MRXSMB_TRANSPORT_POOLTAG);
if (pNewTransportContext != NULL) {
pNewTransportContext->Priority = Priority;
pNewTransportContext->TransportName.MaximumLength = pTransportName->MaximumLength;
pNewTransportContext->TransportName.Length = pTransportName->Length;
pNewTransportContext->TransportName.Buffer = (PWCHAR)((PBYTE)pNewTransportContext +
sizeof(TRANSPORT_BIND_CONTEXT));
RtlCopyMemory(
pNewTransportContext->TransportName.Buffer,
pTransportName->Buffer,
pTransportName->Length);
Status = RxDispatchToWorkerThread(
MRxSmbDeviceObject,
CriticalWorkQueue,
MRxSmbpBindTransportWorkerThreadRoutine,
pNewTransportContext);
} else {
Status = STATUS_INSUFFICIENT_RESOURCES;
}
if (Status != STATUS_SUCCESS) {
InterlockedDecrement(&TdiBindRequestsActive);
SmbCeSignalNetReadyEvent();
}
}
}
}
break;
case TDI_PNP_OP_DEL:
{
PSMBCE_TRANSPORT pTransport;
pTransport = SmbCeFindTransport(pTransportName);
if (pTransport != NULL) {
if (IoGetCurrentProcess() == RxGetRDBSSProcess()) {
MRxSmbpUnbindTransportCallback(pTransport);
} else {
Status = RxDispatchToWorkerThread(
MRxSmbDeviceObject,
CriticalWorkQueue,
MRxSmbpUnbindTransportCallback,
pTransport);
}
}
}
break;
case TDI_PNP_OP_UPDATE:
{
}
break;
case TDI_PNP_OP_NETREADY:
{
TdiPnpNetReadyEventReceived = TRUE;
SmbCeSignalNetReadyEvent();
}
break;
default:
break;
}
}
NTSTATUS
MRxSmbPnPPowerHandler(
IN PUNICODE_STRING DeviceName,
IN PNET_PNP_EVENT PowerEvent,
IN PTDI_PNP_CONTEXT Context1,
IN PTDI_PNP_CONTEXT Context2
)
/*++
Routine Description:
This routine deals with power changes
Notes:
The implementation needs to be completed
--*/
{
NTSTATUS Status;
LONG NumberOfActiveOpens;
Status = STATUS_SUCCESS;
FsRtlEnterFileSystem();
RxPurgeAllFobxs(MRxSmbDeviceObject);
RxScavengeAllFobxs(MRxSmbDeviceObject);
NumberOfActiveOpens = MRxSmbNumberOfSrvOpens;
switch (PowerEvent->NetEvent) {
case NetEventQueryPower:
{
// If the redirector were to return an error on this request there
// is no underlying support to tell the user about the files that
// are open. There are two approaches to doing this.. either the RDR
// rolls its own UI or the PNP manager provides the infra structure.
// The problem with the former is that hibernation becomes a painstaking
// process wherein the user has to contend with a variety of UI.
// Till this is resolved the decision was to use the power mgmt. API
// to manage system initiated hibernate requests and succeed user
// initiated requests after appropriate purging/scavenging.
if (MRxSmbNumberOfSrvOpens > 0) {
DbgPrint(
"RDR: PNP Hibernate Request Status %lx Number of Opens %lx\n",
Status,
MRxSmbNumberOfSrvOpens);
}
Status = STATUS_SUCCESS;
}
break;
case NetEventQueryRemoveDevice:
{
PSMBCEDB_SERVER_ENTRY pServerEntry;
ULONG NumberOfFilesOpen = 0;
PSMBCE_TRANSPORT pTransport = NULL;
pTransport = SmbCeFindTransport(DeviceName);
if (pTransport != NULL) {
SmbCeAcquireSpinLock();
pServerEntry = SmbCeGetFirstServerEntry();
while (pServerEntry != NULL) {
if ((pServerEntry->pTransport != NULL) &&
(pTransport == pServerEntry->pTransport->pTransport)) {
NumberOfFilesOpen += pServerEntry->Server.NumberOfSrvOpens;
}
pServerEntry = SmbCeGetNextServerEntry(pServerEntry);
}
SmbCeReleaseSpinLock();
SmbCeDereferenceTransport(pTransport);
}
}
break;
default:
break;
}
FsRtlExitFileSystem();
return Status;
}
NTSTATUS
MRxSmbRegisterForPnpNotifications()
/*++
Routine Description:
This routine registers with TDI for receiving transport notifications
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
if(MRxSmbTdiNotificationHandle == NULL ) {
UNICODE_STRING ClientName;
TDI_CLIENT_INTERFACE_INFO ClientInterfaceInfo;
RtlInitUnicodeString(&ClientName,L"LanmanWorkStation");
ClientInterfaceInfo.MajorTdiVersion = 2;
ClientInterfaceInfo.MinorTdiVersion = 0;
ClientInterfaceInfo.Unused = 0;
ClientInterfaceInfo.ClientName = &ClientName;
ClientInterfaceInfo.BindingHandler = MRxSmbPnPBindingHandler;
ClientInterfaceInfo.AddAddressHandler = NULL;
ClientInterfaceInfo.DelAddressHandler = NULL;
ClientInterfaceInfo.PnPPowerHandler = MRxSmbPnPPowerHandler;
KeInitializeEvent(
&TdiNetStartupCompletionEvent,
NotificationEvent,
FALSE);
Status = TdiRegisterPnPHandlers (
&ClientInterfaceInfo,
sizeof(ClientInterfaceInfo),
&MRxSmbTdiNotificationHandle );
if (Status == STATUS_SUCCESS) {
LARGE_INTEGER WaitInterval;
WaitInterval.QuadPart = -( 10000 * 2 * 60 * 1000 );
Status = KeWaitForSingleObject(
&TdiNetStartupCompletionEvent,
Executive,
KernelMode,
TRUE,
&WaitInterval);
}
}
return Status;
}
NTSTATUS
MRxSmbDeregisterForPnpNotifications()
/*++
Routine Description:
This routine deregisters the TDI notification mechanism
Notes:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
if( MRxSmbTdiNotificationHandle != NULL ) {
Status = TdiDeregisterPnPHandlers( MRxSmbTdiNotificationHandle );
if( NT_SUCCESS( Status ) ) {
MRxSmbTdiNotificationHandle = NULL;
}
}
return Status;
}
PSMBCE_TRANSPORT_ARRAY
SmbCeReferenceTransportArray(VOID)
/*++
Routine Description:
This routine references and returns the current transport array instance
Return Value:
PSMBCE_TRANSPORT_ARRAY - the pointer of the current transport array instance
Notes:
--*/
{
KIRQL SavedIrql;
PSMBCE_TRANSPORT_ARRAY pTransportArray;
KeAcquireSpinLock(&MRxSmbTransports.Lock,&SavedIrql);
pTransportArray = MRxSmbTransports.pTransportArray;
if (pTransportArray != NULL) {
InterlockedIncrement(&pTransportArray->ReferenceCount);
}
KeReleaseSpinLock(&MRxSmbTransports.Lock,SavedIrql);
return pTransportArray;
}
NTSTATUS
SmbCeDereferenceTransportArray(
PSMBCE_TRANSPORT_ARRAY pTransportArray)
/*++
Routine Description:
This routine dereferences the transport array instance
Arguments:
pTransportArray - the transport array instance
Return Value:
STATUS_SUCCESS - the server transport was successfully dereferenced
Other Status codes correspond to error situations.
Notes:
--*/
{
KIRQL SavedIrql;
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
if (pTransportArray != NULL) {
ASSERT( pTransportArray->ReferenceCount > 0 );
if(InterlockedDecrement(&pTransportArray->ReferenceCount)==0) {
ULONG i;
for(i=0;i<pTransportArray->Count;i++) {
SmbCeDereferenceTransport(pTransportArray->SmbCeTransports[i]);
}
RxFreePool(pTransportArray->SmbCeTransports);
RxFreePool(pTransportArray->LocalAddresses);
RxFreePool(pTransportArray);
}
} else {
Status = STATUS_INVALID_PARAMETER;
}
return Status;
}
NTSTATUS
SmbCeIsServerAvailable(
PUNICODE_STRING Name
)
/*++
Routine Description:
This routine scans the list of "unreachable" servers and returns the status
of the last failed connection attempt.
Return:
STATUS_SUCCESS -> we have no reason to believe this server is unreachable
other -> server is unreachable for this reason
--*/
{
PUNAVAILABLE_SERVER server;
LARGE_INTEGER now;
NTSTATUS status = STATUS_SUCCESS;
PAGED_CODE();
KeQueryTickCount( &now );
ExAcquireResourceExclusive( &UnavailableServerListResource, TRUE );
for( server = (PUNAVAILABLE_SERVER)UnavailableServerList.Flink;
server != (PUNAVAILABLE_SERVER)&UnavailableServerList;
server = (PUNAVAILABLE_SERVER)server->ListEntry.Flink ) {
//
// If this entry has timed out, remove it.
//
if( now.QuadPart > server->Time.QuadPart ) {
PUNAVAILABLE_SERVER tmp;
//
// Unlink this entry from the list and discard it
//
tmp = (PUNAVAILABLE_SERVER)(server->ListEntry.Blink);
RemoveEntryList( &server->ListEntry );
RxFreePool( server );
server = tmp;
continue;
}
//
// See if this entry is the one we want
//
if( RtlCompareUnicodeString( &server->Name, Name, TRUE ) == 0 ) {
status = server->Status;
RxDbgTrace(0, Dbg, ("SmbCeIsServerAvailable: Found %wZ %X\n",
&server->Name, status ));
}
}
ExReleaseResource( &UnavailableServerListResource );
return status;
}
VOID
SmbCeServerIsUnavailable(
PUNICODE_STRING Name,
NTSTATUS Status
)
{
PUNAVAILABLE_SERVER server;
LARGE_INTEGER CurrentTime;
LARGE_INTEGER ExpiryTimeInTicks;
PAGED_CODE();
server = (PUNAVAILABLE_SERVER)RxAllocatePoolWithTag(
PagedPool,
sizeof( *server ) + Name->Length,
MRXSMB_TRANSPORT_POOLTAG
);
if( server == NULL ) {
return;
}
RxDbgTrace(0, Dbg, ("SmbCeServerIsUnavailable: Add %wZ %X\n", Name, Status ));
server->Name.Buffer = (PUSHORT)(server + 1);
server->Name.MaximumLength = Name->Length;
RtlCopyUnicodeString( &server->Name, Name );
KeQueryTickCount( &CurrentTime );
ExpiryTimeInTicks.QuadPart = (1000 * 1000 * 10) / KeQueryTimeIncrement();
ExpiryTimeInTicks.QuadPart = UNAVAILABLE_SERVER_TIME * ExpiryTimeInTicks.QuadPart;
server->Time.QuadPart = CurrentTime.QuadPart + ExpiryTimeInTicks.QuadPart;
server->Status = Status;
ExAcquireResourceExclusive( &UnavailableServerListResource, TRUE );
InsertHeadList( &UnavailableServerList, &server->ListEntry );
ExReleaseResource( &UnavailableServerListResource );
}
VOID
SmbCeDiscardUnavailableServerList(
)
{
PUNAVAILABLE_SERVER server;
PAGED_CODE();
RxDbgTrace(0, Dbg, ("SmbCeDiscardUnavailableServerList\n" ));
FsRtlEnterFileSystem( );
ExAcquireResourceExclusive( &UnavailableServerListResource, TRUE );
while( UnavailableServerList.Flink != &UnavailableServerList ) {
server = (PUNAVAILABLE_SERVER)Unav
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -