/*++ Copyright (c) 1998-2001 Microsoft Corporation Module Name: ultdip.h Abstract: This module contains declarations private to the TDI component. These declarations are placed in a separate .H file to make it easier to access them from within the kernel debugger extension DLL. The TDI package manages two major object types: UL_ENDPOINT and UL_CONNECTION. A UL_ENDPOINT is basically a wrapper around a TDI address object. Each endpoint has two lists of associated UL_CONNECTION objects: one for idle (non-connected) connections and one for active (connected) connections. The active connections list is actually a 64-entry array for better multiprocessor partitioning. A UL_CONNECTION is basically a wrapper around a TDI connection object. Its main purpose is to manage TDI connection state. See the description of UL_CONNECTION_FLAGS below for the gory details. The relationship between these two objects is illustrated in the following diagram: +-----------+ | | |UL_ENDPOINT| | | +---+----+--+ | | | | | | Idle Connections | | +-------------+ +-------------+ +-------------+ | | | | | | | | | +->|UL_CONNECTION|<->|UL_CONNECTION|<->|UL_CONNECTION|<-... | | | | | | | | +-------------+ +-------------+ +-------------+ | | | Active Connections[0] | +-------------+ +-------------+ +-------------+ | | | | | | | +------>|UL_CONNECTION|<->|UL_CONNECTION|<->|UL_CONNECTION|<-... | | | | | | | | +-------------+ +-------------+ +-------------+ | : : | Active Connections[DEFAULT_MAX_CONNECTION_ACTIVE_LISTS-1] | +-------------+ +-------------+ +-------------+ | | | | | | | +------>|UL_CONNECTION|<->|UL_CONNECTION|<->|UL_CONNECTION|<-... | | | | | | +-------------+ +-------------+ +-------------+ Note: Idle connections do not hold references to their owning endpoint, but active connections do. When a listening endpoint is shutdown, all idle connections are simply purged, but active connections must be forcibly disconnected first. Author: Keith Moore (keithmo) 15-Jun-1998 Revision History: --*/ #ifndef _ULTDIP_H_ #define _ULTDIP_H_ #ifdef __cplusplus extern "C" { #endif // // Forward references. // typedef union _ENDPOINT_SYNCH *PENDPOINT_SYNCH; typedef struct _UL_ENDPOINT *PUL_ENDPOINT; typedef union _UL_CONNECTION_FLAGS *PUL_CONNECTION_FLAGS; typedef struct _UL_CONNECTION *PUL_CONNECTION; typedef struct _UL_RECEIVE_BUFFER *PUL_RECEIVE_BUFFER; // // Private constants. // #define MAX_ADDRESS_EA_BUFFER_LENGTH \ sizeof(FILE_FULL_EA_INFORMATION) - 1 + \ TDI_TRANSPORT_ADDRESS_LENGTH + 1 + \ sizeof(TA_IP_ADDRESS) #define MAX_CONNECTION_EA_BUFFER_LENGTH \ sizeof(FILE_FULL_EA_INFORMATION) - 1 + \ TDI_CONNECTION_CONTEXT_LENGTH + 1 + \ sizeof(CONNECTION_CONTEXT) #define TCP_DEVICE_NAME L"\\Device\\Tcp" #define TL_INSTANCE 0 // // Private types. // // // A generic IRP context. This is useful for storing additional completion // information associated with a pending IRP. // // WARNING! All fields of this structure must be explicitly initialized. // typedef struct _UL_IRP_CONTEXT { // // This MUST be the first field in the structure. This is the linkage // used by the lookaside package for storing entries in the lookaside // list. // SINGLE_LIST_ENTRY LookasideEntry; // // Structure signature. // ULONG Signature; // // Either the endpoint or endpoint associated with the IRP. // PVOID pConnectionContext; // // Completion information. // PUL_COMPLETION_ROUTINE pCompletionRoutine; PVOID pCompletionContext; // // Our own allocated IRP if set. // PIRP pOwnIrp; } UL_IRP_CONTEXT, *PUL_IRP_CONTEXT; #define UL_IRP_CONTEXT_SIGNATURE ((ULONG)'CPRI') #define UL_IRP_CONTEXT_SIGNATURE_X MAKE_FREE_SIGNATURE(UL_IRP_CONTEXT_SIGNATURE) #define IS_VALID_IRP_CONTEXT(pIrpContext) \ ( ((pIrpContext) != NULL) && \ ((pIrpContext)->Signature == UL_IRP_CONTEXT_SIGNATURE) ) // // The following union allows us to perform some spinlock-free synchronization // magic using UlInterlockedCompareExchange(). In this case, we can update // the number of idle connections that need to be added to an endpoint, *and* // update the "replenish scheduled" flag atomically. // typedef union _ENDPOINT_SYNCH { struct { LONG ReplenishScheduled:1; LONG IdleConnections:31; }; LONG Value; } ENDPOINT_SYNCH; C_ASSERT( sizeof(ENDPOINT_SYNCH) == sizeof(LONG) ); // // An endpoint is basically our wrapper around a TDI address object. // typedef struct _UL_ENDPOINT { // // Structure signature: UL_ENDPOINT_SIGNATURE // ULONG Signature; // // Reference count. // LONG ReferenceCount; // // Usage count. This is used by the "URL-site-to-endpoint" thingie. // LONG UsageCount; // // Links onto the global endpoint list. // // GlobalEndpointListEntry.Flink is NULL if the endpoint is not // on the global list, g_TdiEndpointListHead, or the // to-be-deleted-soon list, g_TdiDeletedEndpointListHead. // LIST_ENTRY GlobalEndpointListEntry; // // Heads of the per-endpoint connection lists. // Idle connections have a weak reference to 'this', the owning endpoint // SLIST_HEADER IdleConnectionSListHead; // // Use an array of active connections to improve partitioning on MP systems // LIST_ENTRY ActiveConnectionListHead[DEFAULT_MAX_CONNECTION_ACTIVE_LISTS]; // // Index assigned to the next active connection. // LONG ActiveConnectionIndex; // // Spinlock protecting the IdleConnectionSLists. // UL_SPIN_LOCK IdleConnectionSpinLock; // // Spinlocks protecting the ActiveConnectionLists array. // UL_SPIN_LOCK ActiveConnectionSpinLock[DEFAULT_MAX_CONNECTION_ACTIVE_LISTS]; // // Spinlock protecting the endpoint. Use sparingly. // UL_SPIN_LOCK EndpointSpinLock; // // The TDI address object. // UX_TDI_OBJECT AddressObject; // // Indication handlers & user context. // PUL_CONNECTION_REQUEST pConnectionRequestHandler; PUL_CONNECTION_COMPLETE pConnectionCompleteHandler; PUL_CONNECTION_DISCONNECT pConnectionDisconnectHandler; PUL_CONNECTION_DISCONNECT_COMPLETE pConnectionDisconnectCompleteHandler; PUL_CONNECTION_DESTROYED pConnectionDestroyedHandler; PUL_DATA_RECEIVE pDataReceiveHandler; PVOID pListeningContext; // // The local address we're bound to. // PTRANSPORT_ADDRESS pLocalAddress; ULONG LocalAddressLength; // // Is this a secure endpoint? // BOOLEAN Secure; // // Thread work item for deferred actions. // UL_WORK_ITEM WorkItem; // // Synchronizer for idle connection replenishment. // ENDPOINT_SYNCH EndpointSynch; // // An IRP context containing completion information necessary // while shutting down a listening endpoint. // UL_IRP_CONTEXT CleanupIrpContext; #if ENABLE_OWNER_REF_TRACE // // Track owners of the endpoint reference count // POWNER_REF_TRACELOG pOwnerRefTraceLog; PREF_OWNER pEndpointRefOwner; #endif // ENABLE_OWNER_REF_TRACE // // Has this endpoint been moved to the deleted list, // g_TdiDeletedEndpointListHead? // BOOLEAN Deleted; } UL_ENDPOINT; #define UL_ENDPOINT_SIGNATURE ((ULONG)'PDNE') #define UL_ENDPOINT_SIGNATURE_X MAKE_FREE_SIGNATURE(UL_ENDPOINT_SIGNATURE) #define IS_VALID_ENDPOINT(pEndpoint) \ ( ((pEndpoint) != NULL) && \ ((pEndpoint)->Signature == UL_ENDPOINT_SIGNATURE) ) // // Connection flags/state. These flags indicate the current state of a // connection. // // Some of these flags may be simply updated directly. Others require // UlInterlockedCompareExchange() to avoid race conditions. // // The following flags may be updated directly: // // AcceptPending - SET in the TDI connection handler, just before the // accept IRP is returned to the transport. RESET only if the accept // IRP fails. // // The following flags must be updated using UlInterlockedCompareExchange(): // // AcceptComplete - SET in the accept IRP completion handler if the IRP // completed successfully. Once this flag is set, the connection must // be either gracefully disconnected or aborted before the connection // can be closed or reused. // // DisconnectPending - SET just before a graceful disconnect IRP is // issued. // // DisconnectComplete - SET in the graceful disconnect IRP completion // handler. // // AbortPending - SET just before an abortive disconnect IRP is issued. // // AbortComplete - SET in the abortive disconnect IRP completion handler. // // DisconnectIndicated - SET in the TDI disconnect handler for graceful // disconnects issued by the remote client. // // AbortIndicated - SET in the TDI disconnect handler for abortive // disconnects issued by the remote client. // // CleanupPending - SET when cleanup is begun for a connection. This // is necessary to know when the final reference to the connection // can be removed. // // CODEWORK: We can get rid of the CleanupPending flag. It is // only set when either a graceful or abortive disconnect is // issued, and only tested in UlpRemoveFinalReference(). The // test in UlpRemoveFinalReference() can just test for either // (DisconnectPending | AbortPending) instead. // // FinalReferenceRemoved - SET when the final (i.e. "connected") // reference is removed from the connection. // // Note that the flags requiring UlInterlockedCompareExchange() are only SET, // never RESET. This makes the implementation a bit simpler. // // And now a few words about connection management, TDI, and other mysteries. // // Some of the more annoying "features" of TDI are related to connection // management and lifetime. Two of the most onerous issues are: // // 1. Knowing when a connection object handle can be closed without // causing an unwanted connection reset. // // 2. Knowing when TDI has given its last indication on a connection // so that resources can be released, reused, recycled, whatever. // // And, of course, this is further complicated by the inherent asynchronous // nature of the NT I/O architecture and the parallelism of SMP systems. // // There are a few points worth keeping in mind while reading/modifying this // source code or writing clients of this code: // // 1. As soon as an accept IRP is returned from the TDI connection // handler to the transport, the TDI client must be prepared for // any incoming indications, including data receive and disconnect. // In other words, incoming data & disconnect may occur *before* the // accept IRP actually completes. // // 2. A connection is considered "in use" until either both sides have // gracefully disconnected OR either side has aborted the connection. // Closing an "in use" connection will usually result in an abortive // disconnect. // // 3. The various flavors of disconnect (initiated by the local server, // initiated by the remote client, graceful, abortive, etc) may occur // in any order. // typedef union _UL_CONNECTION_FLAGS { // // This field overlays all of the settable flags. This allows us to // update all flags in a thread-safe manner using the // UlInterlockedCompareExchange() API. // LONG Value; struct { ULONG AcceptPending:1; // 00000001 ULONG AcceptComplete:1; // 00000002 ULONG :2; ULONG DisconnectPending:1; // 00000010 ULONG DisconnectComplete:1; // 00000020 ULONG :2; ULONG AbortPending:1; // 00000100 ULONG AbortComplete:1; // 00000200 ULONG :2; ULONG DisconnectIndicated:1; // 00001000 ULONG AbortIndicated:1; // 00002000 ULONG :2; ULONG CleanupBegun:1; // 00010000 ULONG FinalReferenceRemoved:1; // 00020000 ULONG :2; ULONG LocalAddressValid:1; // 00100000 ULONG ReceivePending:1; // 00200000 }; } UL_CONNECTION_FLAGS; C_ASSERT( sizeof(UL_CONNECTION_FLAGS) == sizeof(LONG) ); #define MAKE_CONNECTION_FLAG_ROUTINE(name) \ __inline LONG Make##name##Flag() \ { \ UL_CONNECTION_FLAGS flags = { 0 }; \ flags.name = 1; \ return flags.Value; \ } MAKE_CONNECTION_FLAG_ROUTINE( AcceptPending ); MAKE_CONNECTION_FLAG_ROUTINE( AcceptComplete ); MAKE_CONNECTION_FLAG_ROUTINE( DisconnectPending ); MAKE_CONNECTION_FLAG_ROUTINE( DisconnectComplete ); MAKE_CONNECTION_FLAG_ROUTINE( AbortPending ); MAKE_CONNECTION_FLAG_ROUTINE( AbortComplete ); MAKE_CONNECTION_FLAG_ROUTINE( DisconnectIndicated ); MAKE_CONNECTION_FLAG_ROUTINE( AbortIndicated ); MAKE_CONNECTION_FLAG_ROUTINE( CleanupBegun ); MAKE_CONNECTION_FLAG_ROUTINE( FinalReferenceRemoved ); // // A connection is basically our wrapper around a TDI connection object. // typedef struct _UL_CONNECTION { // // Link onto the per-endpoint idle connection list. // SINGLE_LIST_ENTRY IdleSListEntry; // // Structure signature: UL_CONNECTION_SIGNATURE // ULONG Signature; // // Reference count. // LONG ReferenceCount; // // Connection flags. // UL_CONNECTION_FLAGS ConnectionFlags; // // Cached Irp // PIRP pIrp; // // Addresses and ports. These are in host order. // CODEWORK: Make these transport independent for IPv6. // IPAddr RemoteAddress; USHORT RemotePort; USHORT LocalPort; IPAddr LocalAddress; // // Structure to get LocalAddress when Accept completes // TDI_CONNECTION_INFORMATION TdiConnectionInformation; TA_IP_ADDRESS IpAddress; // // Link onto the per-endpoint active connection list. // LIST_ENTRY ActiveListEntry; // // Index to the ActiveConnectionLists (a random number for better partition // on MP machines). Always zero on UP machines. // ULONG ActiveListIndex; // // The TDI connection object. // UX_TDI_OBJECT ConnectionObject; // // User context. // PVOID pConnectionContext; // // The endpoint associated with this connection. Note that this // ALWAYS points to a valid endpoint. For idle connections, it's // a weak (non referenced) pointer. For active connections, it's // a strong (referenced) pointer. // PUL_ENDPOINT pOwningEndpoint; // // Thread work item for deferred actions. // UL_WORK_ITEM WorkItem; // // Data captured from the listening endpoint at the time the // connection is created. This is captured to reduce references // to the listening endpoint. // PUL_CONNECTION_DESTROYED pConnectionDestroyedHandler; PVOID pListeningContext; // // To synchronize the RawCloseHandler // LONG Terminated; // // Pre-allocated IrpContext for disconnect. // UL_IRP_CONTEXT IrpContext; // // HTTP connection. // UL_HTTP_CONNECTION HttpConnection; // // Filter related info. // UX_FILTER_CONNECTION FilterInfo; // // We've had too many problems with orphaned UL_CONNECTIONs. // Let's make it easy to find them all in the debugger. // LIST_ENTRY GlobalConnectionListEntry; #if REFERENCE_DEBUG // // Private Reference trace log. // PTRACE_LOG pTraceLog; #endif // REFERENCE_DEBUG #if ENABLE_OWNER_REF_TRACE // For ownerref and connection recycling PREF_OWNER pConnRefOwner; LONG MonotonicId; #endif // ENABLE_OWNER_REF_TRACE } UL_CONNECTION, *PUL_CONNECTION; #define UL_CONNECTION_SIGNATURE ((ULONG)'NNOC') #define UL_CONNECTION_SIGNATURE_X MAKE_FREE_SIGNATURE(UL_CONNECTION_SIGNATURE) #define IS_VALID_CONNECTION(pConnection) \ ( ((pConnection) != NULL) && \ ((pConnection)->Signature == UL_CONNECTION_SIGNATURE) ) // // A buffer, containing a precreated receive IRP, a precreated MDL, and // sufficient space for a partial MDL. These buffers are typically used // when passing a receive IRP back to the transport from within our receive // indication handler. // // The buffer structure, IRP, MDLs, and data area are all allocated in a // single pool block. The layout of the block is: // // +-------------------+ // | | // | UL_RECEIVE_BUFFER | // | | // +-------------------+ // | | // | IRP | // | | // +-------------------+ // | | // | MDL | // | | // +-------------------+ // | | // | Partial MDL | // | | // +-------------------+ // | | // | Data Area | // | | // +-------------------+ // // WARNING! All fields of this structure must be explicitly initialized. // typedef struct _UL_RECEIVE_BUFFER { // // This MUST be the first field in the structure. This is the linkage // used by the lookaside package for storing entries in the lookaside // list. // SINGLE_LIST_ENTRY LookasideEntry; // // Structure signature: UL_RECEIVE_BUFFER_SIGNATURE // ULONG Signature; // // Amount of unread data in the data area. // ULONG UnreadDataLength; // // The pre-built receive IRP. // PIRP pIrp; // // The pre-built MDL describing the entire data area. // PMDL pMdl; // // A secondary MDL describing part of the data area. // PMDL pPartialMdl; // // Pointer to the data area for this buffer. // PVOID pDataArea; // // Pointer to the connection referencing this buffer. // PVOID pConnectionContext; } UL_RECEIVE_BUFFER; #define UL_RECEIVE_BUFFER_SIGNATURE ((ULONG)'FUBR') #define UL_RECEIVE_BUFFER_SIGNATURE_X MAKE_FREE_SIGNATURE(UL_RECEIVE_BUFFER_SIGNATURE) #define IS_VALID_RECEIVE_BUFFER(pBuffer) \ ( ((pBuffer) != NULL) && \ ((pBuffer)->Signature == UL_RECEIVE_BUFFER_SIGNATURE) ) // // Private prototypes. // VOID UlpDestroyEndpoint( IN PUL_ENDPOINT pEndpoint ); VOID UlpDestroyConnection( IN PUL_CONNECTION pConnection ); PUL_CONNECTION UlpDequeueIdleConnection( IN PUL_ENDPOINT pEndpoint, IN BOOLEAN ScheduleReplenish ); BOOLEAN UlpEnqueueIdleConnection( IN PUL_CONNECTION pConnection, IN BOOLEAN Replenishing ); VOID UlpEnqueueActiveConnection( IN PUL_CONNECTION pConnection ); NTSTATUS UlpConnectHandler( IN PVOID pTdiEventContext, IN LONG RemoteAddressLength, IN PVOID pRemoteAddress, IN LONG UserDataLength, IN PVOID pUserData, IN LONG OptionsLength, IN PVOID pOptions, OUT CONNECTION_CONTEXT *pConnectionContext, OUT PIRP *pAcceptIrp ); NTSTATUS UlpDisconnectHandler( IN PVOID pTdiEventContext, IN CONNECTION_CONTEXT ConnectionContext, IN LONG DisconnectDataLength, IN PVOID pDisconnectData, IN LONG DisconnectInformationLength, IN PVOID pDisconnectInformation, IN ULONG DisconnectFlags ); NTSTATUS UlpCloseRawConnection( IN PVOID pConnection, IN BOOLEAN AbortiveDisconnect, IN PUL_COMPLETION_ROUTINE pCompletionRoutine, IN PVOID pCompletionContext ); NTSTATUS UlpSendRawData( IN PVOID pObject, IN PMDL pMdlChain, IN ULONG Length, PUL_IRP_CONTEXT pIrpContext ); NTSTATUS UlpReceiveRawData( IN PVOID pConnectionContext, IN PVOID pBuffer, IN ULONG BufferLength, IN PUL_COMPLETION_ROUTINE pCompletionRoutine, IN PVOID pCompletionContext ); NTSTATUS UlpDummyReceiveHandler( IN PVOID pTdiEventContext, IN PVOID ConnectionContext, IN PVOID pTsdu, IN ULONG BytesIndicated, IN ULONG BytesUnreceived, OUT ULONG *pBytesTaken ); NTSTATUS UlpReceiveHandler( IN PVOID pTdiEventContext, IN CONNECTION_CONTEXT ConnectionContext, IN ULONG ReceiveFlags, IN ULONG BytesIndicated, IN ULONG BytesAvailable, OUT ULONG *pBytesTaken, IN PVOID pTsdu, OUT PIRP *pIrp ); NTSTATUS UlpReceiveExpeditedHandler( IN PVOID pTdiEventContext, IN CONNECTION_CONTEXT ConnectionContext, IN ULONG ReceiveFlags, IN ULONG BytesIndicated, IN ULONG BytesAvailable, OUT ULONG *pBytesTaken, IN PVOID pTsdu, OUT PIRP *pIrp ); NTSTATUS UlpRestartAccept( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp, IN PVOID pContext ); NTSTATUS UlpRestartSendData( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp, IN PVOID pContext ); VOID UlpReferenceEndpoint( IN PUL_ENDPOINT pEndpoint OWNER_REFERENCE_DEBUG_FORMAL_PARAMS ); VOID UlpDereferenceEndpoint( IN PUL_ENDPOINT pEndpoint OWNER_REFERENCE_DEBUG_FORMAL_PARAMS ); #if REFERENCE_DEBUG # define REFERENCE_ENDPOINT(endp, action, sig, powner, pprefowner, monoid) \ UlpReferenceEndpoint( (endp), (powner), (pprefowner), (sig), \ action, monoid, (PSTR)__FILE__,(USHORT)__LINE__) # define DEREFERENCE_ENDPOINT(endp, action, sig, powner, pprefowner, monoid)\ UlpDereferenceEndpoint( (endp), (powner), (pprefowner), (sig), \ action, monoid, (PSTR)__FILE__,(USHORT)__LINE__) #else // !REFERENCE_DEBUG # define REFERENCE_ENDPOINT(endp, action, sig, powner, pprefowner, monoid) \ UlpReferenceEndpoint( (endp) ) # define DEREFERENCE_ENDPOINT(endp, action, sig, powner, pprefowner, monoid) \ UlpDereferenceEndpoint( (endp) ) #endif // !REFERENCE_DEBUG #define REFERENCE_ENDPOINT_SELF(endp, action) \ REFERENCE_ENDPOINT( \ (endp), \ (action), \ UL_ENDPOINT_SIGNATURE, \ (endp), \ &(endp)->pEndpointRefOwner, \ -1) #define DEREFERENCE_ENDPOINT_SELF(endp, action) \ DEREFERENCE_ENDPOINT( \ (endp), \ (action), \ UL_ENDPOINT_SIGNATURE, \ (endp), \ &(endp)->pEndpointRefOwner, \ -1) #define REFERENCE_ENDPOINT_CONNECTION(endp, action, pconn) \ REFERENCE_ENDPOINT( \ (endp), \ (action), \ UL_CONNECTION_SIGNATURE, \ (pconn), \ &(pconn)->pConnRefOwner, \ (pconn)->MonotonicId) #define DEREFERENCE_ENDPOINT_CONNECTION(endp, action, pconn)\ DEREFERENCE_ENDPOINT( \ (endp), \ (action), \ UL_CONNECTION_SIGNATURE, \ (pconn), \ &(pconn)->pConnRefOwner, \ (pconn)->MonotonicId) VOID UlpEndpointCleanupWorker( IN PUL_WORK_ITEM pWorkItem ); VOID UlpCleanupConnectionId( IN PUL_WORK_ITEM pWorkItem ); VOID UlpConnectionCleanupWorker( IN PUL_WORK_ITEM pWorkItem ); NTSTATUS UlpAssociateConnection( IN PUL_CONNECTION pConnection, IN PUL_ENDPOINT pEndpoint ); NTSTATUS UlpDisassociateConnection( IN PUL_CONNECTION pConnection ); VOID UlpReplenishEndpoint( IN PUL_ENDPOINT pEndpoint ); VOID UlpReplenishEndpointWorker( IN PUL_WORK_ITEM pWorkItem ); BOOLEAN UlpDecrementIdleConnections( IN PUL_ENDPOINT pEndpoint ); BOOLEAN UlpIncrementIdleConnections( IN PUL_ENDPOINT pEndpoint, IN BOOLEAN Replenishing ); VOID UlpClearReplenishScheduledFlag( IN PUL_ENDPOINT pEndpoint ); NTSTATUS UlpCreateConnection( IN PUL_ENDPOINT pEndpoint, IN ULONG AddressLength, OUT PUL_CONNECTION *ppConnection ); NTSTATUS UlpInitializeConnection( IN PUL_CONNECTION pConnection ); UL_CONNECTION_FLAGS UlpSetConnectionFlag( IN OUT PUL_CONNECTION pConnection, IN LONG NewFlag ); NTSTATUS UlpBeginDisconnect( IN PUL_CONNECTION pConnection, IN PUL_COMPLETION_ROUTINE pCompletionRoutine, IN PVOID pCompletionContext ); NTSTATUS UlpRestartDisconnect( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp, IN PVOID pContext ); NTSTATUS UlpBeginAbort( IN PUL_CONNECTION pConnection, IN PUL_COMPLETION_ROUTINE pCompletionRoutine, IN PVOID pCompletionContext ); NTSTATUS UlpRestartAbort( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp, IN PVOID pContext ); VOID UlpRemoveFinalReference( IN PUL_CONNECTION pConnection, IN UL_CONNECTION_FLAGS Flags ); NTSTATUS UlpRestartReceive( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp, IN PVOID pContext ); NTSTATUS UlpRestartClientReceive( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp, IN PVOID pContext ); NTSTATUS UlpDisconnectAllActiveConnections( IN PUL_ENDPOINT pEndpoint ); VOID UlpUnbindConnectionFromEndpoint( IN PUL_CONNECTION pConnection ); VOID UlpSynchronousIoComplete( IN PVOID pCompletionContext, IN NTSTATUS Status, IN ULONG_PTR Information ); NTSTATUS UlpUrlToAddress( IN PWSTR pSiteUrl, OUT PTA_IP_ADDRESS pAddress, OUT PBOOLEAN pSecure ); PUL_ENDPOINT UlpFindEndpointForAddress( IN PTRANSPORT_ADDRESS pAddress, IN ULONG AddressLength ); NTSTATUS UlpSetNagling( IN PUX_TDI_OBJECT pTdiObject, IN BOOLEAN Flag ); NTSTATUS UlpRestartQueryAddress( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp, IN PVOID pContext ); VOID UlpCleanupEarlyConnection( IN PUL_WORK_ITEM pWorkItem ); NTSTATUS UlpQueryTcpFastSend(); NTSTATUS UlpBuildTdiReceiveBuffer( IN PUX_TDI_OBJECT pTdiObject, IN PUL_CONNECTION pConnection, OUT PIRP *pIrp ); #ifdef __cplusplus }; // extern "C" #endif #endif // _ULTDIP_H_