DWORKER.CPP
/*++ 
 
     Copyright (c) 1996 Intel Corporation 
     Copyright 1996 - 1998 Microsoft Corporation 
     All Rights Reserved 
 
     Permission is granted to use, copy and distribute this software and 
     its documentation for any purpose and without fee, provided, that 
     the above copyright notice and this statement appear in all copies. 
     Intel makes no representations about the suitability of this 
     software for any purpose.  This software is provided "AS IS." 
 
     Intel specifically disclaims all warranties, express or implied, 
     and all liability, including consequential and other indirect 
     damages, for the use of this software, including liability for 
     infringement of any proprietary rights, and including the 
     warranties of merchantability and fitness for a particular purpose. 
     Intel does not assume any responsibility for any errors which may 
     appear in this software nor any responsibility to update it. 
 
 
Module Name: 
 
 
Abstract: 
 
 
--*/ 
 
#include "precomp.h" 
 
 
PDOVERLAPPEDSTRUCTMGR gOverlappedManager; 
 
 
 
 
VOID 
CALLBACK 
APCProc( 
    DWORD Context 
    ) 
/*++ 
Routine Description: 
 
    This routine unpacks the context value passed to WPUQueueApc() and calls 
    the users completion function. This function is called in the clients 
    thread context. 
 
Arguments: 
 
    Context - The context value passed to WPUQueueApc(). 
 
Return Value: 
 
    None 
 
--*/ 
{ 
    LPOVERLAPPED                        lpOverlapped; 
    LPWSAOVERLAPPED_COMPLETION_ROUTINE  UserCompletionRoutine; 
 
    lpOverlapped = (LPOVERLAPPED) Context; 
    UserCompletionRoutine = 
        (LPWSAOVERLAPPED_COMPLETION_ROUTINE)lpOverlapped->Internal; 
    lpOverlapped->Internal = lpOverlapped->Offset; // To make sure it 
                                                   // in no longer is  
                                                   // WSS_OPERATION_IN_PROGRESS 
    UserCompletionRoutine ( 
        lpOverlapped->Offset, 
        lpOverlapped->InternalHigh, 
        lpOverlapped, 
        lpOverlapped->OffsetHigh 
        ); 
 
 
} 
 
VOID 
CALLBACK 
OverlappedCompletionProc( 
    DWORD  dwError, 
    DWORD  cbTransferred, 
    LPWSAOVERLAPPED lpOverlapped, 
    DWORD dwFlags 
    ) 
/*++ 
Routine Description: 
 
    This routine is the completion routine for all overlapped operations 
    initiated with the lower level provider. 
 
Arguments: 
 
    dwError - The error code for the overlapped operation. 
 
    cbTransferred - The number of bytes transfered by the overlapped 
                    operation. 
 
    lpOverlapped - a pointer to the WSAOVERLAPPED struct associated with the 
                   overlapped operation. 
 
    dwFlags -  Not Used must be zero. 
 
Return Value: 
 
    None 
 
--*/ 
{ 
    INT                                Errno; 
    PINTERNALOVERLAPPEDSTRUCT   OverlappedStruct; 
DWORD   OperationType; 
PDPROVIDER   Provider; 
SOCKET   ProviderSocket, Socket; 
WSATHREADID   UserThreadId; 
LPWSAOVERLAPPED_COMPLETION_ROUTINE UserCompletionRoutine; 
LPWSAOVERLAPPED   UserOverlappedStruct; 
 
 
 
    // Get the stored overlapped operation parameters 
OverlappedStruct = gOverlappedManager->GetInternalOverlappedStructure( 
lpOverlapped); 
    // If the completed operation was a recieve operation copy the internal 
    // buffers into the users buffers. 
    if (OverlappedStruct != NULL){ 
OperationType = OverlappedStruct->iolOperationType; 
Socket = OverlappedStruct->iolSocket; 
Provider = OverlappedStruct->iolProvider; 
ProviderSocket = OverlappedStruct->iolProviderSocket; 
UserCompletionRoutine = OverlappedStruct->iolUserCompletionRoutine; 
UserOverlappedStruct = OverlappedStruct->iolUserOverlappedStruct; 
UserThreadId = OverlappedStruct->iolUserThreadId; 
         
if (dwError==WSA_IO_PENDING) 
            Provider->WSPGetOverlappedResult ( 
                    ProviderSocket, 
                    lpOverlapped, 
                    &cbTransferred, 
                    FALSE, 
                    &dwFlags, 
                    (int *)&dwError); 
                                 
 
        switch (OperationType) { 
case WSP_RECV: 
        case WSP_RECVFROM: 
            gBufferManager->CopyBuffer( 
(OverlappedStruct->iolInternalBufferCount <= MAX_FAST_BUFS) 
? &OverlappedStruct->iolInternalBuffers[0] 
: OverlappedStruct->iolpInternalBuffers, 
                OverlappedStruct->iolInternalBufferCount, 
0, 
cbTransferred, 
(OverlappedStruct->iolUserBufferCount <= MAX_FAST_BUFS) 
? &OverlappedStruct->iolUserBuffers[0] 
: OverlappedStruct->iolpUserBuffers, 
                OverlappedStruct->iolUserBufferCount, 
                0); 
            gBufferManager->FreeBuffer( 
(OverlappedStruct->iolInternalBufferCount <= MAX_FAST_BUFS) 
? &OverlappedStruct->iolInternalBuffers[0] 
: OverlappedStruct->iolpInternalBuffers, 
                OverlappedStruct->iolInternalBufferCount); 
if (OverlappedStruct->iolUserBufferCount > MAX_FAST_BUFS) 
delete OverlappedStruct->iolpUserBuffers; 
if (OverlappedStruct->iolInternalBufferCount > MAX_FAST_BUFS) 
delete OverlappedStruct->iolpInternalBuffers; 
break; 
 
case WSP_SEND: 
case WSP_SENDTO: 
if (OverlappedStruct->iolUserBufferCount > MAX_FAST_BUFS) 
delete OverlappedStruct->iolpUserBuffers; 
break; 
 
        case WSP_IOCTL: 
if ((OverlappedStruct->iolIoControlCode==SIO_GET_EXTENSION_FUNCTION_POINTER) 
&& (NO_ERROR==Errno)) { 
Provider->InterceptExtensions ( 
OverlappedStruct->iolInputBuffer, 
OverlappedStruct->iolOutputBuffer, 
&Errno); 
} 
break; 
} 
 
        gOverlappedManager->FreeOverlappedStruct (lpOverlapped); 
 
 
        // If the user requested completion routine notification of the I/O 
        // completion queue an APC to the user thread else signal the users 
        // event. 
        if (UserCompletionRoutine){ 
            UserOverlappedStruct->InternalHigh = cbTransferred; 
            UserOverlappedStruct->Offset = dwError; 
            UserOverlappedStruct->OffsetHigh = dwFlags; 
 
            // Changing Internal field to anything other than 
            // WSS_OPERATON_IN_PROGRESS indicates that operation 
            // is completed and results can be read by WSPGetOverlappedResult, 
            // That's why we set this field last (after updating all others) 
            // Note that event if address of user completion routine is  
            // equal to WSS_OPERATON_IN_PROGRESS (numericall), we are still 
            // safe, because we'll update it again in our completion routine 
            // Also, generally if application specifies completion routine, 
            // it should not use WSAGetOverlappedResult, so essentially by 
            // doing all of this we are just making our code bullet proof 
            UserOverlappedStruct->Internal = (DWORD)UserCompletionRoutine; 
 
            gUpCallTable.lpWPUQueueApc( 
                &UserThreadId, 
                APCProc, 
                (DWORD)UserOverlappedStruct, 
                &Errno); 
 
        } //if 
        else{ 
            UserOverlappedStruct->Offset = dwError; 
            UserOverlappedStruct->OffsetHigh = dwFlags; 
                // Internal and InternalHigh fields will be updated 
                // by the WPUCompleteOverlappedRequest 
            lpWPUCompleteOverlappedRequest ( 
Socket, 
                UserOverlappedStruct, 
                dwError, 
                cbTransferred, 
                &Errno); 
        } //else 
    } //if 
} 
 
 
 
VOID 
InitiateOverlappedOperation ( 
    PINTERNALOVERLAPPEDSTRUCT           OverlappedStruct, 
    LPWSAOVERLAPPED_COMPLETION_ROUTINE  CompletionProc, 
    LPWSATHREADID                       thread_id 
    ) 
/*++ 
Routine Description: 
 
    Initiates overlapped operation with provider. 
 
Arguments: 
 
    OverlappedStruct    - packet operation parameters 
    CompletionProc      - routine to be invoked upon completion 
    thread_id           - id of the thread to which to post APC if any 
Return Value: 
 
    NONE 
--*/ 
{ 
    DWORD                     BytesTransfered; 
    INT                       Errno; 
    INT                       ReturnCode; 
 
    switch (OverlappedStruct->iolOperationType) { 
    case WSP_RECV: 
        ReturnCode = OverlappedStruct->iolProvider->WSPRecv( 
            OverlappedStruct->iolProviderSocket, 
(OverlappedStruct->iolInternalBufferCount <= MAX_FAST_BUFS) 
? &OverlappedStruct->iolInternalBuffers[0] 
: OverlappedStruct->iolpInternalBuffers, 
            OverlappedStruct->iolInternalBufferCount, 
            &BytesTransfered, 
            &OverlappedStruct->iolFlags, 
            &OverlappedStruct->iolInternalOverlappedStruct, 
            CompletionProc, 
            thread_id, 
            &Errno); 
        break; 
 
    case WSP_RECVFROM: 
        ReturnCode = OverlappedStruct->iolProvider->WSPRecvFrom( 
            OverlappedStruct->iolProviderSocket, 
(OverlappedStruct->iolInternalBufferCount <= MAX_FAST_BUFS) 
? &OverlappedStruct->iolInternalBuffers[0] 
: OverlappedStruct->iolpInternalBuffers, 
            OverlappedStruct->iolInternalBufferCount, 
            &BytesTransfered, 
            &OverlappedStruct->iolFlags, 
            OverlappedStruct->iolSockAddr, 
            OverlappedStruct->iolSockAddrLenPtr, 
            &OverlappedStruct->iolInternalOverlappedStruct, 
            CompletionProc, 
            thread_id, 
            &Errno); 
        break; 
 
    case WSP_SEND: 
         ReturnCode = OverlappedStruct->iolProvider->WSPSend( 
            OverlappedStruct->iolProviderSocket, 
(OverlappedStruct->iolUserBufferCount <= MAX_FAST_BUFS) 
? &OverlappedStruct->iolUserBuffers[0] 
: OverlappedStruct->iolpUserBuffers, 
            OverlappedStruct->iolUserBufferCount, 
            &BytesTransfered, 
            OverlappedStruct->iolFlags, 
            &OverlappedStruct->iolInternalOverlappedStruct, 
            CompletionProc, 
            thread_id, 
            &Errno); 
        break; 
    case WSP_SENDTO: 
        ReturnCode = OverlappedStruct->iolProvider->WSPSendTo( 
            OverlappedStruct->iolProviderSocket, 
(OverlappedStruct->iolUserBufferCount <= MAX_FAST_BUFS) 
? &OverlappedStruct->iolUserBuffers[0] 
: OverlappedStruct->iolpUserBuffers, 
            OverlappedStruct->iolUserBufferCount, 
            &BytesTransfered, 
            OverlappedStruct->iolFlags, 
            OverlappedStruct->iolSockAddr, 
            OverlappedStruct->iolSockAddrLen, 
            &OverlappedStruct->iolInternalOverlappedStruct, 
            CompletionProc, 
            thread_id, 
            &Errno); 
        break; 
 
    case WSP_IOCTL: 
        ReturnCode = OverlappedStruct->iolProvider->WSPIoctl( 
            OverlappedStruct->iolProviderSocket, 
            OverlappedStruct->iolIoControlCode, 
            OverlappedStruct->iolInputBuffer, 
            OverlappedStruct->iolInputBufferLength, 
            OverlappedStruct->iolOutputBuffer, 
            OverlappedStruct->iolOutputBufferLength, 
            &BytesTransfered, 
            &OverlappedStruct->iolInternalOverlappedStruct, 
            CompletionProc, 
            thread_id, 
            &Errno); 
        break; 
case ACCEPT_EX: 
        ReturnCode = OverlappedStruct->iolProvider->AcceptEx ( 
            OverlappedStruct->iolListenSocket, 
            OverlappedStruct->iolAcceptSocket, 
            OverlappedStruct->iolOutputBuffer, 
            OverlappedStruct->iolOutputBufferLength, 
            OverlappedStruct->iolLocalAddressLength, 
            OverlappedStruct->iolRemoteAddressLength, 
            &BytesTransfered, 
            &OverlappedStruct->iolInternalOverlappedStruct, 
            &Errno); 
break; 
case TRANSMIT_FILE: 
        ReturnCode = OverlappedStruct->iolProvider->TransmitFile ( 
            OverlappedStruct->iolProviderSocket, 
            OverlappedStruct->iolFileHandle, 
            OverlappedStruct->iolBytesToWrite, 
            OverlappedStruct->iolBytesPerSend, 
            &OverlappedStruct->iolInternalOverlappedStruct, 
((OverlappedStruct->iolTransmitBuffers.HeadLength!=0) 
|| (OverlappedStruct->iolTransmitBuffers.TailLength!=0)) 
? &OverlappedStruct->iolTransmitBuffers 
: NULL, 
            OverlappedStruct->iolReserved, 
            &Errno); 
break; 
default: 
assert (FALSE); 
break; 
    } //switch 
 
    // Complete ourselves if provider fails right away 
    if ((ReturnCode!=NO_ERROR) && (Errno!=WSA_IO_PENDING)) 
        OverlappedCompletionProc ( 
            Errno, 
            0, 
            &OverlappedStruct->iolInternalOverlappedStruct, 
            0); 
 
} 
 
DWORD 
WorkerThreadProc( 
    DWORD  Context 
    ) 
/*++ 
Routine Description: 
 
    Thread procedure passed to CreatThread(). 
 
Arguments: 
 
    Context - Context value passed to CreateThread().  The context value is the 
              worker thread object. 
 
Return Value: 
 
    The Return value of the worker thread 
 
--*/ 
 
{ 
    PDWORKERTHREAD            Thread; 
    HINSTANCE                 HModule; 
    DWORD                     ReturnCode; 
    HModule = LoadLibraryA (gLibraryName); 
 
 
    Thread = (PDWORKERTHREAD) Context; 
    ReturnCode = Thread->WorkerThreadProc(); 
    delete Thread; 
     
    DEBUGF( DBG_TRACE, 
            ("Exiting worker thread.\n")); 
    FreeLibraryAndExitThread (HModule, ReturnCode); 
    return 0;   // Keep compiler happy 
} 
 
 
 
 
  
DWORKERTHREAD::DWORKERTHREAD() 
/*++ 
Routine Description: 
 
    Creates any internal state. 
 
Arguments: 
 
    None 
 
Return Value: 
 
    None 
 
--*/ 
 
{ 
    m_exit_thread = FALSE; 
    m_thread_count = NULL; 
    m_wakeup_semaphore = NULL; 
    m_completion_port = NULL; 
 
    InitializeCriticalSection( 
        &m_overlapped_operation_queue_lock); 
 
    InitializeListHead( 
        &m_overlapped_operation_queue); 
} 
 
VOID 
DWORKERTHREAD::Destroy ( 
    ) 
/*++ 
Routine Description: 
 
    Initiates destruction of the DWORKERTHREAD object. 
    This can't be done syncronously in destructor because this 
    will require waiting for thread object to exit which we want 
    to avoid. 
 
Arguments: 
 
    NONE 
 
Return Value: 
 
    NONE 
--*/ 
{ 
    // If we made it through Initialize. Wake up our threads tell them to exit. 
    if (m_thread_count>0){ 
        m_exit_thread = TRUE; 
        if (m_completion_port) { 
            static OVERLAPPED overlapped; 
            PostQueuedCompletionStatus (m_completion_port, 
                                    0, 
                                    INVALID_SOCKET, 
                                    &overlapped 
                                    ); 
        } 
        else { 
            ReleaseSemaphore (m_wakeup_semaphore, m_thread_count, NULL); 
        } 
        m_thread_count = 0; 
    } 
} 
 
  
DWORKERTHREAD::~DWORKERTHREAD() 
/*++ 
Routine Description: 
 
    destroys any internal state. 
 
Arguments: 
 
    None 
 
Return Value: 
 
    None 
 
--*/ 
{ 
 
    if (m_completion_port) { 
        CloseHandle (m_completion_port); 
        m_completion_port = NULL; 
    } 
    else if (m_wakeup_semaphore){ 
        CloseHandle(m_wakeup_semaphore); 
        m_wakeup_semaphore = NULL; 
    } //if 
 
 
    if (gOverlappedManager) { 
        delete(gOverlappedManager); 
        gOverlappedManager = NULL; 
    } 
 
    DeleteCriticalSection( 
        &m_overlapped_operation_queue_lock); 
 
 
    DEBUGF( DBG_TRACE, 
            ("Destroyed worker thread object\n")); 
} 
 
 
  
INT 
DWORKERTHREAD::Initialize( 
 
    ) 
/*++ 
Routine Description: 
 
    Initializes the DWORKERTHREAD object. 
 
Arguments: 
 
    NONE 
 
Return Value: 
 
    If no error occurs, Initialize() returns NO_ERROR.  Otherwise the value 
    SOCKET_ERROR  is  returned,  and  a  specific  error  code  is available in 
    lpErrno. 
 
--*/ 
{ 
    INT ReturnCode =WSAENOBUFS; 
    DWORD           ThreadId; 
    HANDLE          hThread; 
    SYSTEM_INFO     info; 
DWORDmax_threads; 
 
    DEBUGF( DBG_TRACE, 
            ("Initializing worker thread \n")); 
 
    m_completion_port = CreateIoCompletionPort ( 
                                INVALID_HANDLE_VALUE, 
                                NULL, 
                                0, 
                                0); 
    if (m_completion_port!=NULL) { 
        ReturnCode = NO_ERROR; 
// Don't need extra worker threads if we use completion 
// port -> IO will be initiated/executed in the context 
// of the original client thread and the worker thread 
// will only be used to receive and redirect completion  
// notification. 
max_threads = 1; 
} 
    else { 
        // Create the semaphore we will use to communicat with the worker thread. 
        m_wakeup_semaphore = CreateSemaphore( 
            NULL, 
            0, 
            MAXLONG, 
            NULL); 
        if ( m_wakeup_semaphore){ 
GetSystemInfo (&info); 
max_threads = info.dwNumberOfProcessors; 
            ReturnCode = NO_ERROR; 
        } //if 
    } // if 
 
 
    if (NO_ERROR == ReturnCode){ 
        gOverlappedManager = new DOVERLAPPEDSTRUCTMGR; 
        if (gOverlappedManager!=NULL) { 
            ReturnCode = gOverlappedManager->Initialize(); 
        } 
        else 
            ReturnCode = WSAENOBUFS; 
    } 
 
    // 
    // Create the worker threads. 
    // 
    if (NO_ERROR == ReturnCode){ 
        for (m_thread_count=0; m_thread_count<max_threads; m_thread_count++) { 
            hThread = CreateThread( 
                NULL, 
                0, 
                (LPTHREAD_START_ROUTINE)::WorkerThreadProc, 
                this, 
                0, 
                &ThreadId); 
            if (hThread!=NULL) 
                CloseHandle (hThread); 
            else 
                break; 
        } // for 
if (m_thread_count>0) 
ReturnCode = NO_ERROR; 
else 
ReturnCode = WSAENOBUFS; 
 
    } //if 
 
    if (NO_ERROR != ReturnCode){ 
        //Cleanup any resources we may have allocated. 
        if (m_thread_count>0){ 
            m_exit_thread = TRUE; 
            ReleaseSemaphore(m_wakeup_semaphore, m_thread_count, NULL); 
        } //if 
 
        if (gOverlappedManager) { 
            delete gOverlappedManager; 
            gOverlappedManager = NULL; 
        } 
 
        if (m_wakeup_semaphore) { 
            CloseHandle (m_wakeup_semaphore); 
            m_wakeup_semaphore = NULL; 
        } // if 
 
    } //if 
 
    return(ReturnCode); 
} //Initailize 
 
 
 
 
DWORD 
DWORKERTHREAD::WorkerThreadProc() 
/*++ 
Routine Description: 
 
    The thread procedure for this object. 
 
Arguments: 
 
    NONE 
 
Return Value: 
 
    NO_ERROR 
 
--*/ 
{ 
    INT   Errno; 
 
    gUpCallTable.lpWPUOpenCurrentThread( 
        &m_thread_id, 
        &Errno); 
 
    while (!m_exit_thread){ 
        if (m_completion_port) { 
            BOOL            result; 
            LPOVERLAPPED    lpOverlapped; 
            DWORD           key, cbTransferred; 
            result = GetQueuedCompletionStatus ( 
                        m_completion_port, 
                        &cbTransferred, 
                        &key, 
                        &lpOverlapped, 
                        INFINITE 
                        ); 
            if (m_exit_thread) { 
                DEBUGF (DBG_TRACE, ("Worker thread received signal to exit.\n")); 
                break; 
            } // if 
            else if ((key!=-1) && (lpOverlapped!=NULL)) { 
                OverlappedCompletionProc ( 
                    WSA_IO_PENDING, 
                    cbTransferred, 
                    lpOverlapped, 
                    0); 
            } //else if 
 
        } // if 
        else { 
            DWORD                       ReturnCode; 
            PINTERNALOVERLAPPEDSTRUCT   OverlappedStruct; 
            ReturnCode = WaitForSingleObjectEx( 
                m_wakeup_semaphore, 
                INFINITE, 
                TRUE); 
            if (m_exit_thread) { 
                DEBUGF (DBG_TRACE, ("Worker thread received signal to exit.\n")); 
                break; 
            } // if 
            else if (ReturnCode == WAIT_OBJECT_0){ 
 
                // Is there a queued overlapped operation that needs to be 
                // initiated. 
                OverlappedStruct = NextOverlappedOperation(); 
 
                if (OverlappedStruct){ 
                    InitiateOverlappedOperation ( 
                        OverlappedStruct, 
                        OverlappedCompletionProc, 
                        &m_thread_id); 
                } //if 
            } // else if 
        } //else 
    } //while 
 
    gUpCallTable.lpWPUCloseThread( 
        &m_thread_id, 
        &Errno); 
 
    return(NO_ERROR); 
} 
 
INT 
DWORKERTHREAD::QueueOverlappedRecv( 
    PDSOCKET                           Socket, 
    LPWSABUF                           UserBuffers, 
    DWORD                              UserBufferCount, 
    LPDWORD                            UserBytesRecvd, 
    LPDWORD                            UserFlags, 
    LPWSAOVERLAPPED                    UserOverlappedStruct, 
    LPWSAOVERLAPPED_COMPLETION_ROUTINE UserCompletionRoutine, 
    LPWSATHREADID                      UserThreadId, 
    LPWSABUF                           InternalBuffers, 
    DWORD                              InternalBufferCount, 
    LPINT                              Errno 
    ) 
/*++ 
 
Routine Description: 
 
    this routine allocates an internal overlapped structure stores its 
    arguments in the allocated structure and enqueues the structure for the 
    worker thread to complet the I/O operation. 
 
Arguments: 
 
    Socket      - Socket object 
 
    UserBuffers - The pointer to the user buffer(s). 
 
    UserBufferCount - The number of user buffers. 
 
    UserBytesRecvd - The pointer to the user BytesRecvd parameter. 
 
    UserFlags - A pointer to the user flags argument. 
 
    UserOverlappedStruct - The user overlapped struct pointer. 
 
    UserCompletionRoutine - The user overlapped completion routine. 
 
    UserThreadId - The user thread ID. 
 
    InternalBuffers - A pointer to our internal buffer(s). 
 
    InternalBufferCount - The number of internal buffers. 
 
    Errno - A pointer to the user errno parameter. 
 
Return Value: 
 
    NO_ERROR on success else a valid winsock2 error code. 
 
--*/ 
{ 
    INT ReturnCode; 
 
    PINTERNALOVERLAPPEDSTRUCT OverlappedStruct; 
 
    ReturnCode = SOCKET_ERROR; 
    *Errno = WSAENOBUFS; 
 
    OverlappedStruct = 
        gOverlappedManager->AllocateOverlappedStruct(); 
    if (OverlappedStruct){ 
OverlappedStruct->iolOperationType = WSP_RECV; 
OverlappedStruct->iolSocket = Socket->GetSocketHandle (); 
OverlappedStruct->iolProvider = Socket->GetDProvider(); 
OverlappedStruct->iolProviderSocket = Socket->GetProviderSocket (); 
OverlappedStruct->iolUserOverlappedStruct = UserOverlappedStruct; 
OverlappedStruct->iolUserCompletionRoutine = UserCompletionRoutine; 
OverlappedStruct->iolUserThreadId = *UserThreadId; 
if (UserBufferCount<=MAX_FAST_BUFS) 
memcpy (OverlappedStruct->iolUserBuffers, UserBuffers, 
sizeof (WSABUF)*UserBufferCount); 
else { 
OverlappedStruct->iolpUserBuffers = new WSABUF[UserBufferCount]; 
if (OverlappedStruct->iolpUserBuffers==NULL) { 
gOverlappedManager->FreeOverlappedStruct ( 
&OverlappedStruct->iolInternalOverlappedStruct); 
return ReturnCode; 
} 
memcpy (OverlappedStruct->iolpUserBuffers, UserBuffers, 
sizeof (WSABUF)*UserBufferCount); 
} 
OverlappedStruct->iolUserBufferCount = UserBufferCount; 
if (InternalBufferCount<=MAX_FAST_BUFS) 
memcpy (OverlappedStruct->iolInternalBuffers, InternalBuffers, 
sizeof (WSABUF)*InternalBufferCount); 
else { 
OverlappedStruct->iolpInternalBuffers = new WSABUF[InternalBufferCount]; 
if (OverlappedStruct->iolpInternalBuffers==NULL) { 
if (UserBufferCount>MAX_FAST_BUFS) 
delete OverlappedStruct->iolpUserBuffers; 
gOverlappedManager->FreeOverlappedStruct ( 
&OverlappedStruct->iolInternalOverlappedStruct); 
return ReturnCode; 
} 
memcpy (OverlappedStruct->iolpInternalBuffers, InternalBuffers, 
sizeof (WSABUF)*InternalBufferCount); 
} 
OverlappedStruct->iolInternalBufferCount = InternalBufferCount; 
OverlappedStruct->iolFlags = *UserFlags; 
        AddOverlappedOperation( 
            Socket, 
            OverlappedStruct); 
        *Errno = WSA_IO_PENDING; 
 
    } //if 
    return(ReturnCode); 
} 
 
 
INT 
DWORKERTHREAD::QueueOverlappedRecvFrom( 
    PDSOCKET                           Socket, 
    LPWSABUF                           UserBuffers, 
    DWORD                              UserBufferCount, 
    LPDWORD                            UserBytesRecvd, 
    LPDWORD                            UserFlags, 
    struct sockaddr FAR *              UserFrom, 
    LPINT                              UserFromLen, 
    LPWSAOVERLAPPED                    UserOverlappedStruct, 
    LPWSAOVERLAPPED_COMPLETION_ROUTINE UserCompletionRoutine, 
    LPWSATHREADID                      UserThreadId, 
    LPWSABUF                           InternalBuffers, 
    DWORD                              InternalBufferCount, 
    LPINT                              Errno 
    ) 
/*++ 
 
Routine Description: 
 
    this routine allocates an internal overlapped structure stores its 
    arguments in the allocated structure and enqueues the structure for the 
    worker thread to complet the I/O operation. 
 
Arguments: 
 
    Socket      - Socket object 
 
    UserBuffers - The pointer to the user buffer(s). 
 
    UserBufferCount - The number of user buffers. 
 
    UserBytesRecvd - The pointer to the user BytesRecvd parameter. 
 
    UserFlags - A pointer to the user flags argument. 
 
    UserFrom  - A pinter to the user sockaddr structure, 
 
    UserFromLen - A pointer to the length of UserFrom. 
 
    UserOverlappedStruct - The user overlapped struct pointer. 
 
    UserCompletionRoutine - The user overlapped completion routine. 
 
    UserThreadId - The user thread ID. 
 
    InternalBuffers - A pointer to our internal buffer(s). 
 
    InternalBufferCount - The number of internal buffers. 
 
    Errno - A pointer to the user errno parameter. 
 
Return Value: 
 
    NO_ERROR on success else a valid winsock2 error code. 
 
--*/ 
{ 
    INT                       ReturnCode; 
    PINTERNALOVERLAPPEDSTRUCT OverlappedStruct; 
 
    ReturnCode = SOCKET_ERROR; 
    *Errno = WSAENOBUFS; 
 
    OverlappedStruct = 
        gOverlappedManager->AllocateOverlappedStruct(); 
    if (OverlappedStruct){ 
OverlappedStruct->iolOperationType = WSP_RECVFROM; 
OverlappedStruct->iolSocket = Socket->GetSocketHandle (); 
OverlappedStruct->iolProvider = Socket->GetDProvider(); 
OverlappedStruct->iolProviderSocket = Socket->GetProviderSocket (); 
OverlappedStruct->iolUserOverlappedStruct = UserOverlappedStruct; 
OverlappedStruct->iolUserCompletionRoutine = UserCompletionRoutine; 
OverlappedStruct->iolUserThreadId = *UserThreadId; 
if (UserBufferCount<=MAX_FAST_BUFS) 
memcpy (OverlappedStruct->iolUserBuffers, UserBuffers, 
sizeof (WSABUF)*UserBufferCount); 
else { 
OverlappedStruct->iolpUserBuffers = new WSABUF[UserBufferCount]; 
if (OverlappedStruct->iolpUserBuffers==NULL) { 
gOverlappedManager->FreeOverlappedStruct ( 
&OverlappedStruct->iolInternalOverlappedStruct); 
return ReturnCode; 
} 
memcpy (OverlappedStruct->iolpUserBuffers, UserBuffers, 
sizeof (WSABUF)*UserBufferCount); 
} 
OverlappedStruct->iolUserBufferCount = UserBufferCount; 
if (InternalBufferCount<=MAX_FAST_BUFS) 
memcpy (OverlappedStruct->iolInternalBuffers, InternalBuffers, 
sizeof (WSABUF)*InternalBufferCount); 
else { 
OverlappedStruct->iolpInternalBuffers = new WSABUF[InternalBufferCount]; 
if (OverlappedStruct->iolpInternalBuffers==NULL) { 
if (UserBufferCount>MAX_FAST_BUFS) 
delete OverlappedStruct->iolpUserBuffers; 
gOverlappedManager->FreeOverlappedStruct ( 
&OverlappedStruct->iolInternalOverlappedStruct); 
return ReturnCode; 
} 
memcpy (OverlappedStruct->iolpInternalBuffers, InternalBuffers, 
sizeof (WSABUF)*InternalBufferCount); 
} 
OverlappedStruct->iolInternalBufferCount = InternalBufferCount; 
OverlappedStruct->iolFlags = *UserFlags; 
        OverlappedStruct->iolSockAddr = UserFrom; 
        OverlappedStruct->iolSockAddrLenPtr = UserFromLen; 
 
        AddOverlappedOperation( 
            Socket, 
            OverlappedStruct); 
        *Errno = WSA_IO_PENDING; 
 
    } //if 
    return(ReturnCode); 
} 
 
INT 
DWORKERTHREAD::QueueOverlappedSend( 
    PDSOCKET                           Socket, 
    LPWSABUF                           UserBuffers, 
DWORD                              UserBufferCount, 
    LPDWORD                            UserBytesSent, 
    DWORD                              UserFlags, 
    LPWSAOVERLAPPED                    UserOverlappedStruct, 
    LPWSAOVERLAPPED_COMPLETION_ROUTINE UserCompletionRoutine, 
    LPWSATHREADID                      UserThreadId, 
    LPINT           Errno 
    ) 
/*++ 
 
Routine Description: 
 
    this routine allocates an internal overlapped structure stores its 
    arguments in the allocated structure and enqueues the structure for the 
    worker thread to complet the I/O operation. 
 
Arguments: 
 
    Socket      - Socket object 
 
    UserBuffers - The pointer to the user buffer(s). 
 
    UserBufferCount - The number of user buffers. 
 
    UserBytesSent - The pointer to the user BytesSent parameter. 
 
    UserFlags - The user flags . 
 
    UserOverlappedStruct - The user overlapped struct pointer. 
 
    UserCompletionRoutine - The user overlapped completion routine. 
 
    UserThreadId - The user thread ID. 
 
    InternalBuffers - A pointer to our internal buffer(s). 
 
    InternalBufferCount - The number of internal buffers. 
 
    Errno - A pointer to the user errno parameter. 
 
Return Value: 
 
    NO_ERROR on success else a valid winsock2 error code. 
 
--*/ 
{ 
    INT                       ReturnCode; 
    PINTERNALOVERLAPPEDSTRUCT OverlappedStruct; 
 
    ReturnCode = SOCKET_ERROR; 
    *Errno = WSAENOBUFS; 
 
    OverlappedStruct = 
        gOverlappedManager->AllocateOverlappedStruct(); 
    if (OverlappedStruct){ 
OverlappedStruct->iolOperationType = WSP_SEND; 
OverlappedStruct->iolSocket = Socket->GetSocketHandle (); 
OverlappedStruct->iolProvider = Socket->GetDProvider(); 
OverlappedStruct->iolProviderSocket = Socket->GetProviderSocket (); 
OverlappedStruct->iolUserOverlappedStruct = UserOverlappedStruct; 
OverlappedStruct->iolUserCompletionRoutine = UserCompletionRoutine; 
OverlappedStruct->iolUserThreadId = *UserThreadId; 
if (UserBufferCount<=MAX_FAST_BUFS) 
memcpy (OverlappedStruct->iolUserBuffers, UserBuffers, 
sizeof (WSABUF)*UserBufferCount); 
else { 
OverlappedStruct->iolpUserBuffers = new WSABUF[UserBufferCount]; 
if (OverlappedStruct->iolpUserBuffers==NULL) { 
gOverlappedManager->FreeOverlappedStruct ( 
&OverlappedStruct->iolInternalOverlappedStruct); 
return ReturnCode; 
} 
memcpy (OverlappedStruct->iolpUserBuffers, UserBuffers, 
sizeof (WSABUF)*UserBufferCount); 
} 
OverlappedStruct->iolUserBufferCount = UserBufferCount; 
OverlappedStruct->iolFlags = UserFlags; 
 
        AddOverlappedOperation( 
            Socket, 
            OverlappedStruct); 
 
        *Errno = WSA_IO_PENDING; 
 
    } //if 
    return(ReturnCode); 
} 
 
 
INT 
DWORKERTHREAD::QueueOverlappedSendTo( 
    PDSOCKET                           Socket, 
    LPWSABUF                           UserBuffers, 
    DWORD                              UserBufferCount, 
    LPDWORD                            UserBytesSent, 
    DWORD                              UserFlags, 
    const struct sockaddr FAR *        UserTo, 
    INT                                UserToLen, 
    LPWSAOVERLAPPED                    UserOverlappedStruct, 
    LPWSAOVERLAPPED_COMPLETION_ROUTINE UserCompletionRoutine, 
    LPWSATHREADID                      UserThreadId, 
    LPINT                              Errno 
    ) 
/*++ 
 
Routine Description: 
 
    this routine allocates an internal overlapped structure stores its 
    arguments in the allocated structure and enqueues the structure for the 
    worker thread to complet the I/O operation. 
 
Arguments: 
 
    Socket      - Socket object 
 
    UserBuffers - The pointer to the user buffer(s). 
 
    UserBufferCount - The number of user buffers. 
 
    UserBytesRecvd - The pointer to the user BytesRecvd parameter. 
 
    UserFlags - A pointer to the user flags argument. 
 
    UserTo - A pointer to the user sockaddr structure. 
 
    UserToLen - The length of the user sockaddr structure. 
 
    UserOverlappedStruct - The user overlapped struct pointer. 
 
    UserCompletionRoutine - The user overlapped completion routine. 
 
    UserThreadId - The user thread ID. 
 
    InternalBuffers - A pointer to our internal buffer(s). 
 
    InternalBufferCount - The number of internal buffers. 
 
    Errno - A pointer to the user errno parameter. 
 
Return Value: 
 
    NO_ERROR on success else a valid winsock2 error code. 
 
--*/ 
{ 
    INT                       ReturnCode; 
    PINTERNALOVERLAPPEDSTRUCT OverlappedStruct; 
 
    ReturnCode = SOCKET_ERROR; 
    *Errno = WSAENOBUFS; 
 
    OverlappedStruct = 
        gOverlappedManager->AllocateOverlappedStruct(); 
    if (OverlappedStruct){ 
OverlappedStruct->iolOperationType = WSP_SENDTO; 
OverlappedStruct->iolSocket = Socket->GetSocketHandle (); 
OverlappedStruct->iolProvider = Socket->GetDProvider(); 
OverlappedStruct->iolProviderSocket = Socket->GetProviderSocket (); 
OverlappedStruct->iolUserOverlappedStruct = UserOverlappedStruct; 
OverlappedStruct->iolUserCompletionRoutine = UserCompletionRoutine; 
OverlappedStruct->iolUserThreadId = *UserThreadId; 
if (UserBufferCount<=MAX_FAST_BUFS) 
memcpy (OverlappedStruct->iolUserBuffers, UserBuffers, 
sizeof (WSABUF)*UserBufferCount); 
else { 
OverlappedStruct->iolpUserBuffers = new WSABUF[UserBufferCount]; 
if (OverlappedStruct->iolpUserBuffers==NULL) { 
gOverlappedManager->FreeOverlappedStruct ( 
&OverlappedStruct->iolInternalOverlappedStruct); 
return ReturnCode; 
} 
memcpy (OverlappedStruct->iolpUserBuffers, UserBuffers, 
sizeof (WSABUF)*UserBufferCount); 
} 
OverlappedStruct->iolUserBufferCount = UserBufferCount; 
OverlappedStruct->iolFlags = UserFlags; 
        OverlappedStruct->iolSockAddr = (struct sockaddr FAR *)UserTo; 
        OverlappedStruct->iolSockAddrLen = UserToLen; 
 
        AddOverlappedOperation( 
            Socket, 
            OverlappedStruct); 
 
        *Errno = WSA_IO_PENDING; 
    } //if 
    return(ReturnCode); 
} 
 
INT 
DWORKERTHREAD::QueueOverlappedIoctl( 
    PDSOCKET                           Socket, 
    DWORD                              dwIoControlCode, 
    LPVOID                             lpvInBuffer, 
    DWORD                              cbInBuffer, 
    LPVOID                             lpvOutBuffer, 
    DWORD                              cbOutBuffer, 
    LPDWORD                            lpcbBytesReturned, 
    LPWSAOVERLAPPED                    UserOverlappedStruct, 
    LPWSAOVERLAPPED_COMPLETION_ROUTINE UserCompletionRoutine, 
    LPWSATHREADID                      UserThreadId, 
    LPINT                              Errno 
    ) 
/*++ 
 
Routine Description: 
 
    this routine allocates an internal overlapped structure stores its 
    arguments in the allocated structure and enqueues the structure for the 
    worker thread to complet the I/O operation. 
 
Arguments: 
 
    Socket      - Socket object 
 
    UserBuffers - The pointer to the user buffer(s). 
 
    UserBufferCount - The number of user buffers. 
 
    UserBytesRecvd - The pointer to the user BytesRecvd parameter. 
 
    UserFlags - A pointer to the user flags argument. 
 
    UserTo - A pointer to the user sockaddr structure. 
 
    UserToLen - The length of the user sockaddr structure. 
 
    UserOverlappedStruct - The user overlapped struct pointer. 
 
    UserCompletionRoutine - The user overlapped completion routine. 
 
    UserThreadId - The user thread ID. 
 
    InternalBuffers - A pointer to our internal buffer(s). 
 
    InternalBufferCount - The number of internal buffers. 
 
    Errno - A pointer to the user errno parameter. 
 
Return Value: 
 
    NO_ERROR on success else a valid winsock2 error code. 
 
--*/ 
{ 
    INT                       ReturnCode; 
    PINTERNALOVERLAPPEDSTRUCT OverlappedStruct; 
 
    ReturnCode = SOCKET_ERROR; 
    *Errno = WSAENOBUFS; 
 
    OverlappedStruct = 
        gOverlappedManager->AllocateOverlappedStruct(); 
    if (OverlappedStruct){ 
OverlappedStruct->iolOperationType = WSP_IOCTL; 
OverlappedStruct->iolSocket = Socket->GetSocketHandle (); 
OverlappedStruct->iolProvider = Socket->GetDProvider(); 
OverlappedStruct->iolProviderSocket = Socket->GetProviderSocket (); 
OverlappedStruct->iolUserOverlappedStruct = UserOverlappedStruct; 
OverlappedStruct->iolUserCompletionRoutine = UserCompletionRoutine; 
OverlappedStruct->iolUserThreadId = *UserThreadId; 
OverlappedStruct->iolInputBuffer = lpvInBuffer; 
OverlappedStruct->iolInputBufferLength = cbInBuffer; 
OverlappedStruct->iolOutputBuffer = lpvOutBuffer; 
OverlappedStruct->iolOutputBufferLength = cbOutBuffer; 
OverlappedStruct->iolIoControlCode = dwIoControlCode; 
 
        AddOverlappedOperation( 
            Socket, 
            OverlappedStruct); 
 
        *Errno = WSA_IO_PENDING; 
    } //if 
    return(ReturnCode); 
} 
 
 
 
INT 
DWORKERTHREAD::QueueOverlappedAcceptEx( 
PDSOCKET   ListenSocket, 
PDSOCKET   AcceptSocket, 
LPVOID   lpOutputBuffer, 
DWORD   dwReceiveDataLength, 
DWORD   dwLocalAddressLength, 
DWORD   dwRemoteAddressLength, 
LPWSAOVERLAPPED   UserOverlappedStruct, 
LPINT   Errno 
) { 
    INT                       ReturnCode; 
    PINTERNALOVERLAPPEDSTRUCT OverlappedStruct; 
 
    ReturnCode = SOCKET_ERROR; 
    *Errno = WSAENOBUFS; 
 
    OverlappedStruct = 
        gOverlappedManager->AllocateOverlappedStruct(); 
    if (OverlappedStruct){ 
OverlappedStruct->iolOperationType = ACCEPT_EX; 
OverlappedStruct->iolSocket = ListenSocket->GetSocketHandle (); 
OverlappedStruct->iolProvider = ListenSocket->GetDProvider(); 
OverlappedStruct->iolListenSocket = ListenSocket->GetProviderSocket (); 
OverlappedStruct->iolAcceptSocket = AcceptSocket->GetProviderSocket (); 
OverlappedStruct->iolUserOverlappedStruct = UserOverlappedStruct; 
OverlappedStruct->iolUserCompletionRoutine = NULL; 
OverlappedStruct->iolOutputBuffer = lpOutputBuffer; 
OverlappedStruct->iolOutputBufferLength = dwReceiveDataLength; 
OverlappedStruct->iolLocalAddressLength = dwLocalAddressLength; 
OverlappedStruct->iolRemoteAddressLength = dwRemoteAddressLength; 
 
        AddOverlappedOperation( 
            ListenSocket, 
            OverlappedStruct); 
 
        *Errno = WSA_IO_PENDING; 
    } //if 
    return(ReturnCode); 
} 
 
 
INT 
DWORKERTHREAD::QueueOverlappedTransmitFile( 
PDSOCKETSocket, 
HANDLEhFile, 
DWORDnNumberOfBytesToWrite, 
DWORDnNumberOfBytesPerSend, 
LPWSAOVERLAPPEDUserOverlappedStruct, 
LPTRANSMIT_FILE_BUFFERSlpTransmitBuffers, 
DWORDdwReserved, 
    LPINT                               Errno 
) 
{ 
    INT                       ReturnCode; 
    PINTERNALOVERLAPPEDSTRUCT OverlappedStruct; 
 
    ReturnCode = SOCKET_ERROR; 
    *Errno = WSAENOBUFS; 
 
    OverlappedStruct = 
        gOverlappedManager->AllocateOverlappedStruct(); 
    if (OverlappedStruct){ 
OverlappedStruct->iolOperationType = TRANSMIT_FILE; 
OverlappedStruct->iolSocket = Socket->GetSocketHandle (); 
OverlappedStruct->iolProvider = Socket->GetDProvider(); 
OverlappedStruct->iolProviderSocket = Socket->GetProviderSocket (); 
OverlappedStruct->iolUserOverlappedStruct = UserOverlappedStruct; 
OverlappedStruct->iolUserCompletionRoutine = NULL; 
OverlappedStruct->iolFileHandle = hFile; 
OverlappedStruct->iolBytesToWrite = nNumberOfBytesToWrite; 
OverlappedStruct->iolBytesPerSend = nNumberOfBytesPerSend; 
if (lpTransmitBuffers) 
OverlappedStruct->iolTransmitBuffers = *lpTransmitBuffers; 
else 
OverlappedStruct->iolTransmitBuffers.HeadLength = 
OverlappedStruct->iolTransmitBuffers.TailLength = 0; 
 
OverlappedStruct->iolReserved = dwReserved; 
        AddOverlappedOperation( 
            Socket, 
            OverlappedStruct); 
 
        *Errno = WSA_IO_PENDING; 
    } //if 
    return(ReturnCode); 
} 
 
VOID 
DWORKERTHREAD::AddOverlappedOperation( 
    IN PDSOCKET                  Socket, 
    IN PINTERNALOVERLAPPEDSTRUCT OverlappedOperation 
    ) 
/*++ 
Routine Description: 
 
    This routine adds an internal overlapped structure to the queue of requests 
    to be completed by the worker thread. 
 
Arguments: 
 
    Socket              - A pointer to socket object 
    OverlappedOperation - A pointer to an internal overlapped structure that 
                          describes the operation to be performed by the worker 
                          thread. 
 
Return Value: 
 
    NONE 
--*/ 
{ 
 
    // If we are using completion ports or user requested 
    // completion via APC, initiate operation in the 
    // context of the current thread 
    if (m_completion_port!=NULL) { 
        if (Socket->GetCompletionContext ()==INVALID_SOCKET) { 
            CreateIoCompletionPort ( 
                (HANDLE)OverlappedOperation->iolProviderSocket, 
                m_completion_port, 
                OverlappedOperation->iolSocket, 
                0); 
            Socket->SetCompletionContext (OverlappedOperation->iolSocket); 
        } 
        InitiateOverlappedOperation ( 
            OverlappedOperation, 
            NULL, 
            &OverlappedOperation->iolUserThreadId); 
    } 
    else { 
        EnterCriticalSection(&m_overlapped_operation_queue_lock); 
        InsertTailList( 
            &m_overlapped_operation_queue, 
            &OverlappedOperation->iolListLinkage); 
        LeaveCriticalSection(&m_overlapped_operation_queue_lock); 
        ReleaseSemaphore (m_wakeup_semaphore, 1, NULL); 
    } 
} 
 
 
PINTERNALOVERLAPPEDSTRUCT 
DWORKERTHREAD::NextOverlappedOperation() 
/*++ 
Routine Description: 
 
    This routine returns the first internal overlapped structure from the queue 
    of requests to be completed by the worker thread. 
 
Arguments: 
 
    NONE 
 
Return Value: 
 
    A pointer to an internal overlapped structure or NULL 
 
--*/ 
{ 
    PINTERNALOVERLAPPEDSTRUCT ReturnValue; 
    PLIST_ENTRY               ListEntry; 
 
    ReturnValue = NULL; 
 
    EnterCriticalSection(&m_overlapped_operation_queue_lock); 
 
    if (!IsListEmpty(&m_overlapped_operation_queue)){ 
        ListEntry = RemoveHeadList( 
            &m_overlapped_operation_queue); 
        ReturnValue = CONTAINING_RECORD( 
            ListEntry, 
            INTERNALOVERLAPPEDSTRUCT, 
            iolListLinkage); 
    } //if 
 
    LeaveCriticalSection(&m_overlapped_operation_queue_lock); 
    return(ReturnValue); 
}