Leaked source code of windows server 2003
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.
 
 
 
 
 
 

525 lines
12 KiB

/*++
Copyright (c) 1989-2001 Microsoft Corporation
Module Name:
smbtdi.h
Abstract:
Wrappers for TDI
Author:
Jiandong Ruan
Revision History:
--*/
#ifndef __SMBTDI_H__
#define __SMBTDI_H__
#ifndef TDI_MINIMUM_INDICATE
#define TDI_MINIMUM_INDICATE 128
#endif
#define INVALID_INTERFACE_INDEX (0xffff)
struct _SMB_ASYNC_CONTEXT;
typedef struct _SMB_ASYNC_CONTEXT SMB_ASYNC_CONTEXT, *PSMB_ASYNC_CONTEXT;
typedef void (*PSMB_TDI_COMPLETION) (
IN PSMB_ASYNC_CONTEXT AsyncContext
);
struct _SMB_ASYNC_CONTEXT {
LIST_ENTRY Linkage;
PVOID AsyncInternalContext; // Internally used by the asychn routine.
KTIMER Timer;
KDPC Dpc;
PSMB_TDI_COMPLETION Completion;
PVOID ClientContext;
DWORD Timeout;
NTSTATUS status;
};
#define SMB_TDI_TIMEOUT_INFINITE (0xffffffffU)
void __inline
SmbInitAsyncContext(
IN OUT PSMB_ASYNC_CONTEXT Context,
IN PSMB_TDI_COMPLETION ClientCompletion,
IN PVOID ClientContext,
IN DWORD Timeout
)
{
PAGED_CODE();
InitializeListHead(&Context->Linkage);
Context->AsyncInternalContext = NULL;
Context->Completion = ClientCompletion;
Context->ClientContext = ClientContext;
Context->Timeout = Timeout;
Context->status = STATUS_PENDING;
}
void __inline
SmbAsyncStartTimer(
IN OUT PSMB_ASYNC_CONTEXT Context,
IN PKDEFERRED_ROUTINE TimeoutCompletion
)
{
LARGE_INTEGER DueTime;
PAGED_CODE();
if (Context->Timeout != SMB_TDI_TIMEOUT_INFINITE) {
KeInitializeTimer(&Context->Timer);
KeInitializeDpc(&Context->Dpc, TimeoutCompletion, Context);
DueTime.QuadPart = -Int32x32To64(Context->Timeout, 10000);
KeSetTimer(&Context->Timer, DueTime, &Context->Dpc);
}
}
void __inline
SmbAsyncStopTimer(
IN OUT PSMB_ASYNC_CONTEXT Context
)
{
if (Context->Timeout != SMB_TDI_TIMEOUT_INFINITE) {
KeCancelTimer(&Context->Timer);
}
}
void __inline
SmbAsyncCompleteRequest(
IN OUT PSMB_ASYNC_CONTEXT Context
)
{
SmbAsyncStopTimer(Context);
Context->Completion((PSMB_ASYNC_CONTEXT)Context);
}
/*
* TCP Address object
*/
typedef struct {
PDEVICE_OBJECT DeviceObject;
HANDLE AddressHandle;
PFILE_OBJECT AddressObject;
} SMB_TCP_ADDRESS, *PSMB_TCP_ADDRESS;
VOID __inline
SmbInitTcpAddress(
IN OUT PSMB_TCP_ADDRESS Context
)
{
Context->DeviceObject = NULL;
Context->AddressHandle = NULL;
Context->AddressObject = NULL;
}
BOOL __inline
ValidTcpAddress(
IN OUT PSMB_TCP_ADDRESS Context
)
{
return (Context->DeviceObject && Context->AddressHandle && Context->AddressObject);
}
typedef struct {
HANDLE ConnectHandle;
PFILE_OBJECT ConnectObject;
PVOID UpperConnect;
// for debugging purpose.
// We save a copy here so that we
// can find out the upper connection
// even when UpperConnect is null-ed
// out.
PVOID pLastUprCnt;
} SMB_TCP_CONNECT, *PSMB_TCP_CONNECT;
VOID __inline
SmbInitTcpConnect(
IN OUT PSMB_TCP_CONNECT Context
)
{
Context->ConnectHandle = NULL;
Context->ConnectObject = NULL;
Context->UpperConnect = NULL;
}
BOOL __inline
ValidTcpConnect(
IN OUT PSMB_TCP_CONNECT Context
)
{
return (Context->ConnectHandle && Context->ConnectObject);
}
//
// Placeholder for IP FastQuery routine to determine InterfaceContext + metric for dest addr
//
typedef NTSTATUS
(*PIP4FASTQUERY)(
IN IPAddr Address,
OUT PULONG pIndex,
OUT PULONG pMetric
);
typedef NTSTATUS
(*PIP6FASTQUERY)(
IN PSMB_IP6_ADDRESS Address,
OUT PULONG pIndex,
OUT PULONG pMetric
);
//
// Placeholder for TCP Send routine if Fast Send is possible
//
typedef NTSTATUS
(*PTCPSEND_DISPATCH) (
IN PIRP Irp,
IN PIO_STACK_LOCATION irpsp
);
//
// SMB is bound to either TCP4 or TCP6, or both.
// We have a record for each binding.
//
// We use this data structure to cache our connection object with TCP
// Opening new TCP connection can only be done at PASSIVE level. However,
// due to the following reasons, we need a TCP connection object at
// DISPATCH level,
// 1. For outbound request, we don't know whether we're going to use TCP4
// or TCP6 until the name resoltuion is done. Our DNS name resolution
// completion routine could be called at DISPATCH level.
// 2. For inbound requests, we don't know whether we're going to use TCP4
// or TCP6 until our TdiConnectHandler is called. Again, it is called
// at DISPATCH level.
// To allow SMB get an TCP connection whenever it needs it, we use the following
// data structure to cache the connection object.
//
// The cache algorithm works as follow:
// Parameters: L, M, L < M
// 1. During initialization, we create M TCP connection object;
// 2. Whenever the number of connection objects goes below L, we start a
// worker thread to bring it up to M.
//
typedef struct _SMB_TCP_INFO {
KSPIN_LOCK Lock;
//
// The TDI event context. We need this context to set TDI event handler
//
PVOID TdiEventContext;
SMB_IP_ADDRESS IpAddress; // The local Ip address (in Network Order)
USHORT Port; // The listening port (in network order)
SMB_TCP_ADDRESS InboundAddressObject; // The TCP address object we're lisening on
LIST_ENTRY InboundPool;
LONG InboundNumber; // Number of entries in InboundPool
LONG InboundLow, InboundMid, InboundHigh;
LIST_ENTRY DelayedDestroyList;
//
// Control channel: used to send IOCTLs to TCP
//
USHORT TcpStackSize;
PFILE_OBJECT TCPControlFileObject;
PDEVICE_OBJECT TCPControlDeviceObject;
PFILE_OBJECT IPControlFileObject;
PDEVICE_OBJECT IPControlDeviceObject;
//
// FastSend and FastQuery routine
//
PTCPSEND_DISPATCH FastSend;
PVOID FastQuery;
//
// We use the loopback interface index to determine if an IP is local or not
// 1. Query the outgoing interface from TCP
// 2. If the index of outgoing interface is loopback, then the IP is a local IP.
//
ULONG LoopbackInterfaceIndex;
} SMB_TCP_INFO, *PSMB_TCP_INFO;
//
// Used to store the connection information with TCP
//
typedef struct {
LIST_ENTRY Linkage;
PSMB_TCP_INFO CacheOwner;
//
// The IRP which is used to do the disconnect
// This field is put here only for saving debugging time
// When we see disconnect problem, IRP can tell us
// where we are. (We did see the request pending in TCP forever.)
//
PIRP DisconnectIrp;
SMB_TCP_ADDRESS Address;
SMB_TCP_CONNECT Connect;
} SMB_TCP_CONTEXT, *PSMB_TCP_CONTEXT;
NTSTATUS
SmbInitTCP4(
PSMB_TCP_INFO TcpInfo,
USHORT Port,
PVOID TdiEventContext
);
NTSTATUS
SmbInitTCP6(
PSMB_TCP_INFO TcpInfo,
USHORT Port,
PVOID TdiEventContext
);
NTSTATUS
SmbShutdownTCP(
PSMB_TCP_INFO TcpInfo
);
VOID
SmbReadTCPConf(
IN HANDLE hKey,
PSMB_TCP_INFO TcpInfo
);
NTSTATUS
SmbSynchConnCache(
PSMB_TCP_INFO TcpInfo,
BOOL Cleanup
);
PSMB_TCP_CONTEXT
SmbAllocateOutbound(
PSMB_TCP_INFO TcpInfo
);
VOID
SmbFreeOutbound(
PSMB_TCP_CONTEXT TcpCtx
);
PSMB_TCP_CONTEXT
SmbAllocateInbound(
PSMB_TCP_INFO TcpInfo
);
VOID
SmbFreeInbound(
PSMB_TCP_CONTEXT TcpCtx
);
VOID
SmbFreeTcpContext(
PSMB_TCP_CONTEXT TcpCtx
);
VOID
SmbDelayedDestroyTcpContext(
PSMB_TCP_CONTEXT TcpCtx
);
typedef struct _SMB_DEVICE SMB_DEVICE, *PSMB_DEVICE;
NTSTATUS
SmbWakeupWorkerThread(
IN PSMB_DEVICE DeviceObject
);
VOID __inline
SmbInitTcpContext(
IN OUT PSMB_TCP_CONTEXT Context
)
{
InitializeListHead(&Context->Linkage);
Context->DisconnectIrp = NULL;
SmbInitTcpAddress(&Context->Address);
SmbInitTcpConnect(&Context->Connect);
}
NTSTATUS
SmbOpenTcpAddress(
IN PSMB_IP_ADDRESS addr,
IN USHORT port,
IN OUT PSMB_TCP_ADDRESS context
);
NTSTATUS
SmbOpenUdpAddress(
IN PSMB_IP_ADDRESS addr,
IN USHORT port,
IN OUT PSMB_TCP_ADDRESS context
);
NTSTATUS
SmbCloseAddress(
IN OUT PSMB_TCP_ADDRESS context
);
NTSTATUS
SmbOpenTcpConnection(
IN PSMB_TCP_ADDRESS Address,
IN OUT PSMB_TCP_CONNECT Connect,
IN PVOID ConnectionContext
);
NTSTATUS
SmbCloseTcpConnection(
IN OUT PSMB_TCP_CONNECT Connect
);
NTSTATUS
TdiSetEventHandler(
PFILE_OBJECT FileObject,
ULONG EventType,
PVOID EventHandler,
PVOID Context
);
typedef struct {
SMB_ASYNC_CONTEXT;
ULONG Id; // TransactionId
PTDI_ADDRESS_NETBIOS_UNICODE_EX pUnicodeAddress;
UNICODE_STRING FQDN;
LONG ipaddr_num;
SMB_IP_ADDRESS ipaddr[SMB_MAX_IPADDRS_PER_HOST];
} SMB_GETHOST_CONTEXT, *PSMB_GETHOST_CONTEXT;
BOOL
SmbLookupHost(
WCHAR *host,
PSMB_IP_ADDRESS ipaddr
);
void
SmbAsyncGetHostByName(
IN PUNICODE_STRING Name,
IN PSMB_GETHOST_CONTEXT Context
);
typedef struct {
SMB_ASYNC_CONTEXT;
// Local end point
SMB_TCP_CONNECT TcpConnect;
//
// GetHostByName returns multiple IP address.
// We try to connect to each of them until
// we succeed in making a connection
//
// the result of GetHostByName
PSMB_GETHOST_CONTEXT pSmbGetHostContext;
// the IP address currently being tried
USHORT usCurrentIP;
PIO_WORKITEM pIoWorkItem;
} SMB_CONNECT_CONTEXT, *PSMB_CONNECT_CONTEXT;
typedef struct _SMB_CONNECT SMB_CONNECT, *PSMB_CONNECT;
typedef struct _SMB_DEVICE SMB_DEVICE, *PSMB_DEVICE;
typedef NTSTATUS (*PRECEIVE_HANDLER) (
IN PSMB_DEVICE DeviceObject,
IN PSMB_CONNECT ConnectObject,
IN ULONG ReceiveFlags,
IN LONG BytesIndicated,
IN LONG BytesAvailable,
OUT LONG *BytesTaken,
IN PVOID Tsdu,
OUT PIRP *Irp
);
#ifndef __SMB_KDEXT__
void
SmbAsyncConnect(
IN PSMB_IP_ADDRESS ipaddr,
IN USHORT port,
IN PSMB_CONNECT_CONTEXT Context
);
NTSTATUS
SmbTcpDisconnect(
PSMB_TCP_CONTEXT TcpContext,
LONG TimeoutMilliseconds,
ULONG Flags
);
NTSTATUS
SmbAsynchTcpDisconnect(
PSMB_TCP_CONTEXT TcpContext,
ULONG Flags
);
NTSTATUS
SmbSetTcpEventHandlers(
PFILE_OBJECT AddressObject,
PVOID Context
);
NTSTATUS
SubmitSynchTdiRequest (
IN PFILE_OBJECT FileObject,
IN PIRP Irp
);
NTSTATUS
SmbSendIoctl(
PFILE_OBJECT FileObject,
ULONG Ioctl,
PVOID InBuf,
ULONG InBufSize,
PVOID OutBuf,
ULONG *OutBufSize
);
NTSTATUS
SmbSetTcpInfo(
IN PFILE_OBJECT FileObject,
IN ULONG Entity,
IN ULONG Class,
IN ULONG ToiId,
IN ULONG ToiType,
IN ULONG InfoBufferValue
);
#define ATTACH_FSP(Attached) \
do { \
if (PsGetCurrentProcess() != SmbCfg.FspProcess) { \
Attached = TRUE; \
KeAttachProcess((PRKPROCESS)SmbCfg.FspProcess); \
} else { \
Attached = FALSE; \
} \
} while(0)
#define DETACH_FSP(Attached) \
do { \
if (Attached) { \
KeDetachProcess(); \
} \
} while(0)
#endif // __SMB_KDEXT__
#endif // __SMBTDI_H__