00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "lspdef.h"
00020
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023
00024 #pragma warning(disable:4127) // disable "conditional expression is constant" warning
00025 #pragma warning(disable:4702) // disable "unreacheable code" warning
00026
00027
00028
00029
00030
00031
00032
00033
00034 static LIST_ENTRY gPendingOperations;
00035
00036 static LIST_ENTRY gFreeOverlappedPlus;
00037
00038
00039
00040
00041
00042
00043
00044
00045 HANDLE *gWorkerThread = NULL,
00046 gWakeupSemaphore = NULL,
00047 gIocp = NULL;
00048 DWORD gThreadCount = (DWORD)-1;
00049
00050
00051
00052
00053
00054
00055
00056
00057 LPWSAOVERLAPPEDPLUS
00058 AllocOverlappedStructure(
00059 SOCK_INFO *SocketContext
00060 );
00061
00062
00063 void
00064 FreeOverlappedStructure(
00065 WSAOVERLAPPEDPLUS *olp
00066 );
00067
00068
00069 int
00070 ExecuteOverlappedOperation(
00071 WSAOVERLAPPEDPLUS *lpOverlapped,
00072 BOOL bSynchronous
00073 );
00074
00075
00076
00077 int
00078 EnqueueOverlappedOperation(
00079 WSAOVERLAPPEDPLUS *op
00080 );
00081
00082
00083 void
00084 SetOverlappedInProgress(
00085 OVERLAPPED *ol
00086 );
00087
00088
00089
00090 DWORD WINAPI
00091 OverlappedManagerThread(
00092 LPVOID lpParam
00093 );
00094
00095
00096 VOID CALLBACK
00097 CallUserApcProc(
00098 ULONG_PTR Context
00099 );
00100
00101
00102
00103 void
00104 CheckForContextCleanup(
00105 WSAOVERLAPPEDPLUS *ol
00106 );
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126 int
00127 InitOverlappedManager(
00128 )
00129 {
00130 DWORD i;
00131 int ret = NO_ERROR;
00132
00133 EnterCriticalSection( &gOverlappedCS );
00134
00135
00136
00137
00138
00139 if ( NULL != gWorkerThread )
00140 goto cleanup;
00141
00142 InitializeListHead( &gFreeOverlappedPlus );
00143 InitializeListHead( &gPendingOperations );
00144
00145
00146
00147
00148
00149 gIocp = CreateIoCompletionPort(
00150 INVALID_HANDLE_VALUE,
00151 NULL,
00152 (ULONG_PTR)0,
00153 0
00154 );
00155 if ( NULL != gIocp )
00156 {
00157 SYSTEM_INFO sinfo;
00158
00159
00160
00161
00162 GetSystemInfo( &sinfo );
00163 gThreadCount = sinfo.dwNumberOfProcessors;
00164 }
00165 else
00166 {
00167
00168
00169
00170
00171 gWakeupSemaphore = CreateSemaphore(
00172 NULL,
00173 0,
00174 MAXLONG,
00175 NULL
00176 );
00177 if ( NULL == gWakeupSemaphore )
00178 {
00179 dbgprint("InitOverlappedManager: CreateSemaphore() failed: %d", GetLastError());
00180 ret = WSAEPROVIDERFAILEDINIT;
00181 goto cleanup;
00182 }
00183
00184
00185
00186
00187 gThreadCount = 1;
00188 }
00189
00190 dbgprint("Creating %d threads", gThreadCount);
00191
00192 gWorkerThread = (HANDLE *) LspAlloc(
00193 sizeof( HANDLE ) * gThreadCount,
00194 &ret
00195 );
00196 if ( NULL == gWorkerThread )
00197 {
00198 goto cleanup;
00199 }
00200
00201
00202
00203
00204 for(i=0; i < gThreadCount ;i++)
00205 {
00206 gWorkerThread[i] = CreateThread(
00207 NULL,
00208 0,
00209 OverlappedManagerThread,
00210 (LPVOID)gIocp,
00211 0,
00212 NULL
00213 );
00214 if ( NULL == gWorkerThread[ i ] )
00215 {
00216 dbgprint("InitOverlappedManager: CreateThread() failed: %d", GetLastError());
00217 ret = WSAEPROVIDERFAILEDINIT;
00218 goto cleanup;
00219 }
00220 }
00221
00222 cleanup:
00223
00224 LeaveCriticalSection( &gOverlappedCS );
00225
00226 return ret;
00227 }
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237 int
00238 StopOverlappedManager(
00239 )
00240 {
00241 DWORD i;
00242 int ret = NO_ERROR;
00243
00244 EnterCriticalSection( &gOverlappedCS );
00245
00246
00247
00248
00249 if ( NULL != gIocp )
00250 {
00251 for(i=0; i < gThreadCount ;i++)
00252 {
00253 ret = PostQueuedCompletionStatus(
00254 gIocp,
00255 (DWORD)-1,
00256 0,
00257 NULL
00258 );
00259 if ( 0 == ret )
00260 {
00261 dbgprint("PostQueuedCompletionStatus() failed: %d", GetLastError());
00262 }
00263 }
00264
00265
00266
00267
00268
00269 }
00270 else
00271 {
00272
00273
00274
00275
00276
00277 LIST_ENTRY *entry = NULL;
00278 WSAOVERLAPPEDPLUS *olp = NULL;
00279
00280 while ( !IsListEmpty( &gPendingOperations ) )
00281 {
00282 entry = RemoveHeadList( &gPendingOperations );
00283
00284 olp = CONTAINING_RECORD( entry, WSAOVERLAPPEDPLUS, Link );
00285
00286 FreeOverlappedStructure( olp );
00287 }
00288 }
00289
00290 if ( NULL != gWorkerThread )
00291 {
00292 ret = WaitForMultipleObjectsEx( gThreadCount, gWorkerThread, TRUE, 5000, TRUE );
00293 if ( WAIT_TIMEOUT == ret )
00294 dbgprint("StopOverlappedManager: Timed out waiting for IOCP threads to exit!");
00295 else if ( WAIT_FAILED == ret )
00296 dbgprint("StopOverlappedManager: WaitForMultipleObjectsEx failed: %d",
00297 GetLastError());
00298 else
00299 dbgprint("StopOverlappedManager: All worker threads stopped!");
00300
00301 for(i=0; i < gThreadCount ;i++)
00302 {
00303 CloseHandle( gWorkerThread[ i ] );
00304 gWorkerThread[ i ] = NULL;
00305
00306 dbgprint("Closing overlapped thread(s)");
00307 }
00308
00309 LspFree( gWorkerThread );
00310 gWorkerThread = NULL;
00311 }
00312
00313
00314
00315
00316 if ( NULL != gIocp )
00317 {
00318 CloseHandle( gIocp );
00319 gIocp = NULL;
00320 }
00321
00322 if ( NULL != gWakeupSemaphore )
00323 {
00324 CloseHandle( gWakeupSemaphore );
00325 gWakeupSemaphore = NULL;
00326 }
00327
00328 LeaveCriticalSection( &gOverlappedCS );
00329
00330 return ret;
00331 }
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343 int
00344 QueueOverlappedOperation(
00345 WSAOVERLAPPEDPLUS *ol,
00346 SOCK_INFO *SocketContext
00347 )
00348 {
00349 BOOL bSynchronous = FALSE;
00350 int err;
00351
00352
00353
00354
00355
00356 __try
00357 {
00358 SetOverlappedInProgress( ol->lpCallerOverlapped );
00359 }
00360 __except( EXCEPTION_EXECUTE_HANDLER )
00361 {
00362 return WSAEFAULT;
00363 }
00364
00365 if ( NULL != gIocp )
00366 {
00367
00368
00369
00370
00371 AcquireSocketLock( SocketContext );
00372
00373 if ( NULL == SocketContext->hIocp )
00374 {
00375 SocketContext->hIocp = CreateIoCompletionPort(
00376 (HANDLE)ol->ProviderSocket,
00377 gIocp,
00378 ol->CallerSocket,
00379 0
00380 );
00381 if ( NULL == SocketContext->hIocp )
00382 {
00383 if ( ERROR_INVALID_PARAMETER == (err = GetLastError() ) )
00384 {
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396 bSynchronous = TRUE;
00397 }
00398 else
00399 {
00400 dbgprint("QueueOverlappedOperation: CreateIoCompletionPort() "
00401 "failed: %d (Prov %d Iocp 0x%x Caller 0x%x 0)",
00402 err, ol->ProviderSocket,
00403 gIocp, ol->CallerSocket);
00404 }
00405 }
00406
00407 dbgprint("Adding provider handle %X to IOCP", ol->ProviderSocket);
00408 }
00409
00410 ReleaseSocketLock( SocketContext );
00411
00412
00413
00414
00415 return ExecuteOverlappedOperation( ol, bSynchronous );
00416 }
00417 else
00418 {
00419
00420
00421 return EnqueueOverlappedOperation( ol );
00422 }
00423 }
00424
00425
00426
00427
00428
00429
00430
00431
00432 int
00433 EnqueueOverlappedOperation(
00434 WSAOVERLAPPEDPLUS *op
00435 )
00436 {
00437 int ret = WSA_IO_PENDING;
00438
00439 EnterCriticalSection( &gOverlappedCS );
00440
00441 if ( NULL == op )
00442 {
00443 dbgprint("EnqueueOverlappedOperation: op == NULL!");
00444 ret = WSAEFAULT;
00445 goto cleanup;
00446 }
00447
00448 InsertTailList( &gPendingOperations, &op->Link );
00449
00450
00451
00452
00453
00454 ReleaseSemaphore( gWakeupSemaphore, 1, NULL );
00455
00456 cleanup:
00457
00458 LeaveCriticalSection( &gOverlappedCS );
00459
00460 return ret;
00461 }
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471 WSAOVERLAPPEDPLUS *
00472 DequeueOverlappedOperation(
00473 )
00474 {
00475 WSAOVERLAPPEDPLUS *op = NULL;
00476 LIST_ENTRY *link = NULL;
00477
00478 EnterCriticalSection( &gOverlappedCS );
00479
00480 link = RemoveHeadList( &gPendingOperations );
00481
00482 op = CONTAINING_RECORD( link, WSAOVERLAPPEDPLUS, Link );
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496 LeaveCriticalSection( &gOverlappedCS );
00497
00498 return op;
00499 }
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511 int
00512 ExecuteOverlappedOperation(
00513 WSAOVERLAPPEDPLUS *ol,
00514 BOOL bSynchronous
00515 )
00516 {
00517 LPWSAOVERLAPPED_COMPLETION_ROUTINE routine = NULL;
00518 PROVIDER *Provider;
00519 DWORD *lpdwFlags = NULL,
00520 *lpdwBytes = NULL;
00521 int ret=SOCKET_ERROR, err=0;
00522
00523 if ( NULL == gIocp)
00524 routine = IntermediateCompletionRoutine;
00525
00526 Provider = ol->Provider;
00527
00528
00529
00530
00531
00532
00533
00534 if ( NULL != ol->lpCallerOverlapped->hEvent )
00535 {
00536 ULONG_PTR ptr = 1;
00537
00538 ResetEvent( (HANDLE) ( (ULONG_PTR) ol->lpCallerOverlapped->hEvent & ~ptr ) );
00539 }
00540
00541 switch ( ol->Operation )
00542 {
00543 case LSP_OP_IOCTL:
00544 lpdwFlags = NULL;
00545 lpdwBytes = &ol->IoctlArgs.cbBytesReturned;
00546 ret = Provider->NextProcTable.lpWSPIoctl(
00547 ol->ProviderSocket,
00548 ol->IoctlArgs.dwIoControlCode,
00549 ol->IoctlArgs.lpvInBuffer,
00550 ol->IoctlArgs.cbInBuffer,
00551 ol->IoctlArgs.lpvOutBuffer,
00552 ol->IoctlArgs.cbOutBuffer,
00553 &ol->IoctlArgs.cbBytesReturned,
00554 &ol->ProviderOverlapped,
00555 routine,
00556 &ol->CallerThreadId,
00557 &err
00558 );
00559 break;
00560
00561 case LSP_OP_RECV:
00562 lpdwFlags = &ol->RecvArgs.dwFlags;
00563 lpdwBytes = &ol->RecvArgs.dwNumberOfBytesRecvd;
00564 ret = Provider->NextProcTable.lpWSPRecv(
00565 ol->ProviderSocket,
00566 ol->RecvArgs.lpBuffers,
00567 ol->RecvArgs.dwBufferCount,
00568 &ol->RecvArgs.dwNumberOfBytesRecvd,
00569 &ol->RecvArgs.dwFlags,
00570 &ol->ProviderOverlapped,
00571 routine,
00572 &ol->CallerThreadId,
00573 &err
00574 );
00575 break;
00576
00577 case LSP_OP_RECVFROM:
00578 lpdwFlags = &ol->RecvFromArgs.dwFlags;
00579 lpdwBytes = &ol->RecvFromArgs.dwNumberOfBytesRecvd;
00580 ret = Provider->NextProcTable.lpWSPRecvFrom(
00581 ol->ProviderSocket,
00582 ol->RecvFromArgs.lpBuffers,
00583 ol->RecvFromArgs.dwBufferCount,
00584 &ol->RecvFromArgs.dwNumberOfBytesRecvd,
00585 &ol->RecvFromArgs.dwFlags,
00586 ol->RecvFromArgs.lpFrom,
00587 ol->RecvFromArgs.lpFromLen,
00588 &ol->ProviderOverlapped,
00589 routine,
00590 &ol->CallerThreadId,
00591 &err
00592 );
00593 break;
00594
00595 case LSP_OP_SEND:
00596 lpdwFlags = &ol->SendArgs.dwFlags;
00597 lpdwBytes = &ol->SendArgs.dwNumberOfBytesSent;
00598 ret = Provider->NextProcTable.lpWSPSend(
00599 ol->ProviderSocket,
00600 ol->SendArgs.lpBuffers,
00601 ol->SendArgs.dwBufferCount,
00602 &ol->SendArgs.dwNumberOfBytesSent,
00603 ol->SendArgs.dwFlags,
00604 &ol->ProviderOverlapped,
00605 routine,
00606 &ol->CallerThreadId,
00607 &err
00608 );
00609 break;
00610
00611 case LSP_OP_SENDTO:
00612 lpdwFlags = &ol->SendToArgs.dwFlags;
00613 lpdwBytes = &ol->SendToArgs.dwNumberOfBytesSent;
00614 ret = Provider->NextProcTable.lpWSPSendTo(
00615 ol->ProviderSocket,
00616 ol->SendToArgs.lpBuffers,
00617 ol->SendToArgs.dwBufferCount,
00618 &ol->SendToArgs.dwNumberOfBytesSent,
00619 ol->SendToArgs.dwFlags,
00620 (SOCKADDR *)&ol->SendToArgs.To,
00621 ol->SendToArgs.iToLen,
00622 &ol->ProviderOverlapped,
00623 routine,
00624 &ol->CallerThreadId,
00625 &err
00626 );
00627 break;
00628
00629 case LSP_OP_TRANSMITFILE:
00630 lpdwFlags = &ol->TransmitFileArgs.dwFlags;
00631 lpdwBytes = NULL;
00632 ret = Provider->NextProcTableExt.lpfnTransmitFile(
00633 ol->ProviderSocket,
00634 ol->TransmitFileArgs.hFile,
00635 ol->TransmitFileArgs.nNumberOfBytesToWrite,
00636 ol->TransmitFileArgs.nNumberOfBytesPerSend,
00637 &ol->ProviderOverlapped,
00638 ol->TransmitFileArgs.lpTransmitBuffers,
00639 ol->TransmitFileArgs.dwFlags
00640 );
00641 if ( FALSE == ret )
00642 {
00643 ret = SOCKET_ERROR;
00644 err = WSAGetLastError();
00645 WSASetLastError(err);
00646 }
00647 else
00648 {
00649 ret = NO_ERROR;
00650 }
00651 break;
00652
00653 case LSP_OP_ACCEPTEX:
00654 lpdwFlags = NULL;
00655 lpdwBytes = &ol->AcceptExArgs.dwBytesReceived;
00656 ret = Provider->NextProcTableExt.lpfnAcceptEx(
00657 ol->ProviderSocket,
00658 ol->AcceptExArgs.sProviderAcceptSocket,
00659 ol->AcceptExArgs.lpOutputBuffer,
00660 ol->AcceptExArgs.dwReceiveDataLength,
00661 ol->AcceptExArgs.dwLocalAddressLength,
00662 ol->AcceptExArgs.dwRemoteAddressLength,
00663 &ol->AcceptExArgs.dwBytesReceived,
00664 &ol->ProviderOverlapped
00665 );
00666 if ( FALSE == ret )
00667 {
00668 ret = SOCKET_ERROR;
00669 err = WSAGetLastError();
00670 WSASetLastError(err);
00671 }
00672 else
00673 {
00674 ret = NO_ERROR;
00675 }
00676 break;
00677
00678 case LSP_OP_CONNECTEX:
00679 lpdwFlags = NULL;
00680 lpdwBytes = &ol->ConnectExArgs.dwBytesSent;
00681 ret = Provider->NextProcTableExt.lpfnConnectEx(
00682 ol->ProviderSocket,
00683 (SOCKADDR *)&ol->ConnectExArgs.name,
00684 ol->ConnectExArgs.namelen,
00685 ol->ConnectExArgs.lpSendBuffer,
00686 ol->ConnectExArgs.dwSendDataLength,
00687 &ol->ConnectExArgs.dwBytesSent,
00688 &ol->ProviderOverlapped
00689 );
00690 if ( FALSE == ret )
00691 {
00692 ret = SOCKET_ERROR;
00693 err = WSAGetLastError();
00694 WSASetLastError(err);
00695 }
00696 else
00697 {
00698 ret = NO_ERROR;
00699 }
00700 break;
00701
00702 case LSP_OP_DISCONNECTEX:
00703 lpdwFlags = &ol->DisconnectExArgs.dwFlags;
00704 lpdwBytes = NULL;
00705 ret = Provider->NextProcTableExt.lpfnDisconnectEx(
00706 ol->ProviderSocket,
00707 &ol->ProviderOverlapped,
00708 ol->DisconnectExArgs.dwFlags,
00709 ol->DisconnectExArgs.dwReserved
00710 );
00711 if ( FALSE == ret )
00712 {
00713 ret = SOCKET_ERROR;
00714 err = WSAGetLastError();
00715 WSASetLastError(err);
00716 }
00717 else
00718 {
00719 ret = NO_ERROR;
00720 }
00721 break;
00722
00723 case LSP_OP_TRANSMITPACKETS:
00724 lpdwFlags = &ol->TransmitPacketsArgs.dwFlags;
00725 lpdwBytes = NULL;
00726 ret = Provider->NextProcTableExt.lpfnTransmitPackets(
00727 ol->ProviderSocket,
00728 ol->TransmitPacketsArgs.lpPacketArray,
00729 ol->TransmitPacketsArgs.nElementCount,
00730 ol->TransmitPacketsArgs.nSendSize,
00731 &ol->ProviderOverlapped,
00732 ol->TransmitPacketsArgs.dwFlags
00733 );
00734 if ( FALSE == ret )
00735 {
00736 ret = SOCKET_ERROR;
00737 err = WSAGetLastError();
00738 WSASetLastError(err);
00739 }
00740 else
00741 {
00742 ret = NO_ERROR;
00743 }
00744 break;
00745
00746 case LSP_OP_WSARECVMSG:
00747 lpdwFlags = NULL;
00748 lpdwBytes = &ol->WSARecvMsgArgs.dwNumberOfBytesRecvd;
00749 ret = Provider->NextProcTableExt.lpfnWSARecvMsg(
00750 ol->ProviderSocket,
00751 ol->WSARecvMsgArgs.lpMsg,
00752 &ol->WSARecvMsgArgs.dwNumberOfBytesRecvd,
00753 &ol->ProviderOverlapped,
00754 routine
00755 );
00756 if ( SOCKET_ERROR == ret )
00757 {
00758 err = WSAGetLastError();
00759 WSASetLastError( err );
00760 }
00761 else
00762 {
00763 ret = NO_ERROR;
00764 }
00765 break;
00766
00767 default:
00768 dbgprint("ExecuteOverlappedOperation: Unknown operation!");
00769 ret = SOCKET_ERROR;
00770 break;
00771 }
00772
00773 if ( ( NO_ERROR != ret ) && ( WSA_IO_PENDING != err ) )
00774 {
00775
00776
00777
00778 ol->lpCallerOverlapped->Offset = (lpdwFlags ? *lpdwFlags : 0);
00779 ol->lpCallerOverlapped->OffsetHigh = err;
00780 ol->lpCallerOverlapped->InternalHigh = (lpdwBytes ? *lpdwBytes : 0);
00781 ol->lpCallerOverlapped->Internal = 0;
00782
00783 dbgprint("Overlap op failed immediately: %d", ol->Error);
00784
00785 CheckForContextCleanup( ol );
00786
00787 FreeOverlappedStructure( ol );
00788 }
00789 else if ( ( NO_ERROR == ret ) && ( FALSE == bSynchronous ) )
00790 {
00791
00792
00793
00794
00795
00796
00797
00798
00799 err = WSA_IO_PENDING;
00800 ret = SOCKET_ERROR;
00801 }
00802 else if ( ( NO_ERROR == ret ) && ( TRUE == bSynchronous ) )
00803 {
00804
00805
00806
00807 dbgprint("Succeeded without error - synchronous socket though");
00808 }
00809
00810 return ( ( NO_ERROR == ret ) ? ret : err );
00811 }
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821 DWORD WINAPI
00822 OverlappedManagerThread(
00823 LPVOID lpParam
00824 )
00825 {
00826 WSAOVERLAPPEDPLUS *pOverlapPlus = NULL;
00827 WSAOVERLAPPED *pOverlap = NULL;
00828 HANDLE hIocp = (HANDLE)lpParam;
00829 ULONG_PTR key;
00830 DWORD dwBytesXfered;
00831 int ret;
00832
00833 while ( TRUE )
00834 {
00835 if ( NULL != hIocp )
00836 {
00837 ret = GetQueuedCompletionStatus(
00838 hIocp,
00839 &dwBytesXfered,
00840 &key,
00841 &pOverlap,
00842 INFINITE
00843 );
00844 if ( 0 == ret )
00845 {
00846
00847
00848 dbgprint("GetQueuedCompletionStatus() failed: %d", GetLastError());
00849 }
00850
00851 if ( -1 == dwBytesXfered )
00852 {
00853
00854
00855
00856
00857
00858 dbgprint("OverlappedManagerThread: Received exit message");
00859 goto cleanup;
00860 }
00861
00862
00863 IntermediateCompletionRoutine(
00864 WSA_IO_PENDING,
00865 dwBytesXfered,
00866 pOverlap,
00867 0
00868 );
00869 }
00870 else
00871 {
00872 ret = WaitForSingleObjectEx(
00873 gWakeupSemaphore,
00874 INFINITE,
00875 TRUE
00876 );
00877 if ( WAIT_IO_COMPLETION == ret )
00878 {
00879
00880 continue;
00881 }
00882 else if ( WAIT_OBJECT_0 == ret )
00883 {
00884 pOverlapPlus = DequeueOverlappedOperation();
00885 if ( NULL == pOverlapPlus )
00886 continue;
00887
00888 ExecuteOverlappedOperation( pOverlapPlus, FALSE );
00889 }
00890 else
00891 {
00892 dbgprint("OverlappedManagerThread: WaitForSingleObjectEx() failed: %d (error = %d)",
00893 ret, GetLastError() );
00894 goto cleanup;
00895 }
00896 }
00897 }
00898
00899 cleanup:
00900
00901 ExitThread( 0 );
00902 }
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912 LPWSAOVERLAPPEDPLUS
00913 AllocOverlappedStructure(
00914 SOCK_INFO *SocketContext
00915 )
00916 {
00917 LPWSAOVERLAPPEDPLUS lpWorkerOverlappedPlus = NULL;
00918
00919 if ( NULL == SocketContext )
00920 {
00921 dbgprint("AllocOverlappedStructure: SocketContext is NULL!");
00922 return NULL;
00923 }
00924
00925 EnterCriticalSection( &gOverlappedCS );
00926
00927 AcquireSocketLock( SocketContext );
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938 (SocketContext->dwOutstandingAsync)++;
00939
00940 if ( IsListEmpty( &gFreeOverlappedPlus ) )
00941 {
00942 int err;
00943
00944 lpWorkerOverlappedPlus = (WSAOVERLAPPEDPLUS *) LspAlloc(
00945 sizeof(WSAOVERLAPPEDPLUS),
00946 &err
00947 );
00948 }
00949 else
00950 {
00951 LIST_ENTRY *entry = NULL;
00952
00953 entry = RemoveHeadList( &gFreeOverlappedPlus );
00954
00955 lpWorkerOverlappedPlus = CONTAINING_RECORD( entry, WSAOVERLAPPEDPLUS, Link );
00956 }
00957
00958 ReleaseSocketLock( SocketContext );
00959
00960 LeaveCriticalSection( &gOverlappedCS );
00961
00962 return lpWorkerOverlappedPlus;
00963 }
00964
00965
00966
00967
00968
00969
00970
00971
00972 void
00973 FreeOverlappedStructure(
00974 WSAOVERLAPPEDPLUS *olp
00975 )
00976 {
00977 EnterCriticalSection( &gOverlappedCS );
00978
00979 switch ( olp->Operation )
00980 {
00981 case LSP_OP_RECV:
00982 FreeWSABuf( olp->RecvArgs.lpBuffers );
00983 break;
00984
00985 case LSP_OP_RECVFROM:
00986 FreeWSABuf( olp->RecvFromArgs.lpBuffers );
00987 break;
00988
00989 case LSP_OP_SEND:
00990 FreeWSABuf( olp->SendArgs.lpBuffers );
00991 break;
00992
00993 case LSP_OP_SENDTO:
00994 FreeWSABuf( olp->SendToArgs.lpBuffers );
00995 break;
00996
00997 default:
00998 break;
00999 }
01000
01001 memset( olp, 0, sizeof( WSAOVERLAPPEDPLUS ) );
01002
01003 InsertHeadList( &gFreeOverlappedPlus, &olp->Link );
01004
01005 LeaveCriticalSection( &gOverlappedCS );
01006 }
01007
01008
01009
01010
01011
01012
01013
01014
01015 void
01016 SetOverlappedInProgress(
01017 OVERLAPPED *ol
01018 )
01019 {
01020 ol->Internal = WSS_OPERATION_IN_PROGRESS;
01021 ol->InternalHigh = 0;
01022 }
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032 void CALLBACK
01033 IntermediateCompletionRoutine(
01034 DWORD dwError,
01035 DWORD cbTransferred,
01036 LPWSAOVERLAPPED lpOverlapped,
01037 DWORD dwFlags
01038 )
01039 {
01040 LPWSAOVERLAPPEDPLUS olp = NULL;
01041 SOCK_INFO *SocketContext = NULL,
01042 *AcceptSocketContext = NULL;
01043 int Error,
01044 ret;
01045
01046 if ( NULL == lpOverlapped )
01047 {
01048 dbgprint("IntermediateCompletionRoutine: lpOverlapped == NULL!");
01049 goto cleanup;
01050 }
01051
01052 ASSERT( lpOverlapped );
01053
01054 olp = CONTAINING_RECORD( lpOverlapped, WSAOVERLAPPEDPLUS, ProviderOverlapped );
01055
01056
01057
01058
01059
01060
01061
01062 SocketContext = FindAndRefSocketContext(olp->CallerSocket, &Error);
01063 if ( NULL == SocketContext )
01064 {
01065 dbgprint( "IntermediateCompletionRoutine: FindAndRefSocketContext failed!" );
01066 goto cleanup;
01067 }
01068
01069 if ( WSA_IO_PENDING == dwError )
01070 {
01071
01072
01073
01074
01075 ASSERT( olp->Provider );
01076 ASSERT( olp->Provider->NextProcTable.lpWSPGetOverlappedResult );
01077
01078 dwError = NO_ERROR;
01079 ret = olp->Provider->NextProcTable.lpWSPGetOverlappedResult(
01080 olp->ProviderSocket,
01081 lpOverlapped,
01082 &cbTransferred,
01083 FALSE,
01084 &dwFlags,
01085 (int *)&dwError
01086 );
01087
01088 if ( FALSE == ret )
01089 {
01090 dbgprint("IntermediateCompletionRoutine: WSPGetOverlappedResult failed: %d", dwError);
01091 }
01092 else
01093 {
01094
01095 dbgprint("Bytes transferred on socket 0x%x: %d [op=%d; err=%d]",
01096 olp->CallerSocket, cbTransferred, olp->Operation, dwError);
01097 }
01098 }
01099
01100 olp->lpCallerOverlapped->Offset = dwFlags;
01101 olp->lpCallerOverlapped->OffsetHigh = dwError;
01102 olp->lpCallerOverlapped->InternalHigh = cbTransferred;
01103
01104 SocketContext->LastError = dwError;
01105
01106 if ( 0 == dwError )
01107 {
01108 AcquireSocketLock( SocketContext );
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118 switch ( olp->Operation )
01119 {
01120 case LSP_OP_RECV:
01121 SocketContext->BytesRecv += cbTransferred;
01122 FreeWSABuf(olp->RecvArgs.lpBuffers);
01123 break;
01124
01125 case LSP_OP_RECVFROM:
01126 SocketContext->BytesRecv += cbTransferred;
01127 FreeWSABuf(olp->RecvFromArgs.lpBuffers);
01128 break;
01129
01130 case LSP_OP_SEND:
01131 SocketContext->BytesSent += cbTransferred;
01132 FreeWSABuf(olp->SendArgs.lpBuffers);
01133 break;
01134
01135 case LSP_OP_SENDTO:
01136 SocketContext->BytesSent += cbTransferred;
01137 FreeWSABuf(olp->SendToArgs.lpBuffers);
01138 break;
01139
01140 case LSP_OP_TRANSMITFILE:
01141 SocketContext->BytesSent += cbTransferred;
01142 break;
01143
01144 case LSP_OP_TRANSMITPACKETS:
01145 SocketContext->BytesSent += cbTransferred;
01146 break;
01147
01148 case LSP_OP_ACCEPTEX:
01149
01150 ReleaseSocketLock( SocketContext );
01151
01152 AcceptSocketContext = FindAndRefSocketContext(
01153 olp->AcceptExArgs.sAcceptSocket,
01154 &Error
01155 );
01156 if (AcceptSocketContext == NULL)
01157 {
01158 dbgprint( "IntermediateCompletionRoutine: FindAndRefSocketContext failed! (LSP_OP_ACCEPTEX)" );
01159 }
01160 AcquireSocketLock( AcceptSocketContext );
01161
01162 AcceptSocketContext->BytesRecv += cbTransferred;
01163
01164 ReleaseSocketLock( AcceptSocketContext );
01165
01166 DerefSocketContext(AcceptSocketContext, &Error);
01167
01168 break;
01169
01170 case LSP_OP_CONNECTEX:
01171 SocketContext->BytesSent += cbTransferred;
01172 break;
01173
01174 case LSP_OP_WSARECVMSG:
01175 SocketContext->BytesRecv += cbTransferred;
01176 break;
01177
01178 default:
01179 break;
01180 }
01181
01182 if ( LSP_OP_ACCEPTEX != olp->Operation )
01183 ReleaseSocketLock( SocketContext );
01184 }
01185
01186 DerefSocketContext( SocketContext, &Error );
01187
01188 if ( NULL != olp->lpCallerCompletionRoutine )
01189 {
01190
01191
01192
01193 olp->lpCallerOverlapped->Internal = (ULONG_PTR)olp->lpCallerCompletionRoutine;
01194
01195 ret = gMainUpCallTable.lpWPUQueueApc(
01196 &olp->CallerThreadId,
01197 CallUserApcProc,
01198 (DWORD_PTR) olp->lpCallerOverlapped,
01199 &Error
01200 );
01201 if ( SOCKET_ERROR == ret )
01202 {
01203 dbgprint("IntermediateCompletionRoutine: WPUQueueApc() failed: %d", Error);
01204 }
01205 }
01206 else
01207 {
01208
01209
01210
01211 ret = WPUCompleteOverlappedRequest(
01212 olp->CallerSocket,
01213 olp->lpCallerOverlapped,
01214 dwError,
01215 cbTransferred,
01216 &Error
01217 );
01218 if ( SOCKET_ERROR == ret )
01219 {
01220 dbgprint("WPUCompleteOverlappedRequest failed: %d (provider socket 0x%x)",
01221 Error, olp->CallerSocket );
01222 }
01223 }
01224
01225 if ( ( NULL != olp ) && ( TRUE == olp->CloseThread ) )
01226 {
01227 ret = gMainUpCallTable.lpWPUCloseThread( &olp->CallerThreadId, &Error );
01228 if ( SOCKET_ERROR == ret )
01229 {
01230 dbgprint("WPUCloseThread failed: %d", Error );
01231 }
01232 olp->CloseThread = FALSE;
01233 }
01234
01235
01236
01237
01238 CheckForContextCleanup( olp );
01239
01240 cleanup:
01241
01242 if ( NULL != olp )
01243 FreeOverlappedStructure( olp );
01244
01245 return;
01246 }
01247
01248
01249
01250
01251
01252
01253
01254 VOID CALLBACK
01255 CallUserApcProc(
01256 ULONG_PTR Context
01257 )
01258 {
01259 LPOVERLAPPED lpOverlapped;
01260 LPWSAOVERLAPPED_COMPLETION_ROUTINE UserCompletionRoutine;
01261
01262 lpOverlapped = (LPOVERLAPPED) Context;
01263 UserCompletionRoutine = (LPWSAOVERLAPPED_COMPLETION_ROUTINE)lpOverlapped->Internal;
01264 lpOverlapped->Internal = 0;
01265
01266 UserCompletionRoutine(
01267 (DWORD)lpOverlapped->OffsetHigh,
01268 (DWORD)lpOverlapped->InternalHigh,
01269 lpOverlapped,
01270 (DWORD)lpOverlapped->Offset
01271 );
01272 return;
01273 }
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284 void
01285 CheckForContextCleanup(
01286 WSAOVERLAPPEDPLUS *ol
01287 )
01288 {
01289 SOCK_INFO *SocketContext = NULL;
01290 int Error,
01291 ret;
01292
01293 SocketContext = FindAndRefSocketContext( ol->CallerSocket, &Error );
01294 if ( NULL == SocketContext )
01295 {
01296 dbgprint( "CheckForContextCleanup: FindAndRefSocketContext failed!" );
01297 return;
01298 }
01299
01300 EnterCriticalSection( &gCriticalSection );
01301
01302 AcquireSocketLock( ol->SockInfo );
01303
01304 (ol->SockInfo->dwOutstandingAsync)--;
01305
01306 if ( ( TRUE == ol->SockInfo->bClosing ) &&
01307 ( 0 == ol->SockInfo->dwOutstandingAsync ) &&
01308 ( 1 == ol->SockInfo->RefCount )
01309 )
01310 {
01311
01312
01313
01314
01315
01316 ret = gMainUpCallTable.lpWPUCloseSocketHandle(
01317 ol->CallerSocket,
01318 &ol->Error
01319 );
01320 if ( SOCKET_ERROR == ret )
01321 {
01322 dbgprint("CheckForContextClenaup: WPUCloseSocketHandle() failed: %d", ol->Error);
01323 }
01324
01325 ol->SockInfo->LayeredSocket = INVALID_SOCKET;
01326
01327 RemoveSocketInfo( ol->SockInfo->Provider, ol->SockInfo );
01328
01329 dbgprint("CheckForContxtCleanup: Closing socket %d Bytes Sent [%lu] Bytes Recv [%lu]",
01330 ol->CallerSocket, ol->SockInfo->BytesSent, ol->SockInfo->BytesRecv);
01331
01332 ReleaseSocketLock( ol->SockInfo );
01333
01334 ol->SockInfo = NULL;
01335
01336 FreeSockInfo( SocketContext );
01337
01338 goto cleanup;
01339 }
01340
01341 ReleaseSocketLock( ol->SockInfo );
01342
01343 DerefSocketContext( SocketContext, &Error );
01344
01345 cleanup:
01346
01347 LeaveCriticalSection( &gCriticalSection );
01348
01349 return;
01350 }
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360 WSAOVERLAPPEDPLUS *
01361 PrepareOverlappedOperation(
01362 SOCK_INFO *SocketContext,
01363 LspOperation operation,
01364 WSABUF *lpBuffers,
01365 DWORD dwBufferCount,
01366 LPWSAOVERLAPPED lpOverlapped,
01367 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
01368 LPWSATHREADID lpThreadId,
01369 int *lpErrno
01370 )
01371 {
01372 WSAOVERLAPPEDPLUS *ProviderOverlapped = NULL;
01373 int ret = SOCKET_ERROR,
01374 err = 0;
01375
01376
01377 ProviderOverlapped = AllocOverlappedStructure( SocketContext );
01378 if ( NULL == ProviderOverlapped )
01379 {
01380 *lpErrno = WSAENOBUFS;
01381 goto cleanup;
01382 }
01383
01384 __try
01385 {
01386
01387
01388 if ( ( NULL == lpCompletionRoutine ) &&
01389 ( NULL != lpOverlapped->hEvent ) )
01390 {
01391 ULONG_PTR ptr = 1;
01392
01393 ret = ResetEvent( (HANDLE) ( (ULONG_PTR) lpOverlapped->hEvent & ~ptr ) );
01394 if (ret == 0)
01395 {
01396 *lpErrno = ERROR_INVALID_HANDLE;
01397 ret = SOCKET_ERROR;
01398 goto cleanup;
01399 }
01400 }
01401
01402
01403 CopyOffset( &ProviderOverlapped->ProviderOverlapped, lpOverlapped );
01404
01405 }
01406 __except(EXCEPTION_EXECUTE_HANDLER)
01407 {
01408 *lpErrno = WSAEFAULT;
01409 goto cleanup;
01410 }
01411
01412 if ( NULL != lpThreadId )
01413 {
01414 ProviderOverlapped->CallerThreadId = *lpThreadId;
01415 }
01416 else
01417 {
01418
01419 ret = gMainUpCallTable.lpWPUOpenCurrentThread( &ProviderOverlapped->CallerThreadId, &err );
01420 if ( SOCKET_ERROR == ret )
01421 {
01422 dbgprint("WPUOpenCurrentThread failed: %d", err);
01423 }
01424 else
01425 {
01426
01427 ProviderOverlapped->CloseThread = TRUE;
01428 }
01429 }
01430
01431
01432 ProviderOverlapped->Provider = SocketContext->Provider;
01433 ProviderOverlapped->lpCallerOverlapped = lpOverlapped;
01434 ProviderOverlapped->lpCallerCompletionRoutine = lpCompletionRoutine;
01435 ProviderOverlapped->SockInfo = SocketContext;
01436 ProviderOverlapped->CallerSocket = SocketContext->LayeredSocket;
01437 ProviderOverlapped->ProviderSocket = SocketContext->ProviderSocket;
01438 ProviderOverlapped->Error = NO_ERROR;
01439 ProviderOverlapped->Operation = operation;
01440
01441 if ( ( NULL != lpBuffers) && ( dwBufferCount ) )
01442 {
01443
01444 switch ( operation )
01445 {
01446 case LSP_OP_RECV:
01447 ProviderOverlapped->RecvArgs.dwBufferCount = dwBufferCount;
01448 ProviderOverlapped->RecvArgs.lpBuffers = CopyWSABuf(
01449 lpBuffers,
01450 dwBufferCount,
01451 lpErrno
01452 );
01453 if ( NULL == ProviderOverlapped->RecvArgs.lpBuffers )
01454 goto cleanup;
01455
01456 break;
01457
01458 case LSP_OP_RECVFROM:
01459 ProviderOverlapped->RecvFromArgs.dwBufferCount = dwBufferCount;
01460 ProviderOverlapped->RecvFromArgs.lpBuffers = CopyWSABuf(
01461 lpBuffers,
01462 dwBufferCount,
01463 lpErrno
01464 );
01465 if ( NULL == ProviderOverlapped->RecvFromArgs.lpBuffers )
01466 goto cleanup;
01467
01468 break;
01469
01470 case LSP_OP_SEND:
01471 ProviderOverlapped->SendArgs.dwBufferCount = dwBufferCount;
01472 ProviderOverlapped->SendArgs.lpBuffers = CopyWSABuf(
01473 lpBuffers,
01474 dwBufferCount,
01475 lpErrno
01476 );
01477 if ( NULL == ProviderOverlapped->SendArgs.lpBuffers )
01478 goto cleanup;
01479
01480 break;
01481
01482 case LSP_OP_SENDTO:
01483 ProviderOverlapped->SendToArgs.dwBufferCount = dwBufferCount;
01484 ProviderOverlapped->SendToArgs.lpBuffers = CopyWSABuf(
01485 lpBuffers,
01486 dwBufferCount,
01487 lpErrno
01488 );
01489 if ( NULL == ProviderOverlapped->SendToArgs.lpBuffers )
01490 goto cleanup;
01491
01492 break;
01493
01494 default:
01495 break;
01496 }
01497 }
01498
01499 ret = NO_ERROR;
01500
01501 cleanup:
01502
01503 if ( SOCKET_ERROR == ret )
01504 {
01505 UndoOverlappedOperation( SocketContext, ProviderOverlapped );
01506 ProviderOverlapped = NULL;
01507 }
01508 else
01509 {
01510 ASSERT( NO_ERROR == ret );
01511 }
01512
01513 return ProviderOverlapped;
01514 }
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524 void
01525 UndoOverlappedOperation(
01526 SOCK_INFO *SocketContext,
01527 WSAOVERLAPPEDPLUS *ProviderOverlapped
01528 )
01529 {
01530 AcquireSocketLock( SocketContext );
01531 (SocketContext->dwOutstandingAsync)--;
01532 ReleaseSocketLock( SocketContext );
01533
01534 FreeOverlappedStructure( ProviderOverlapped );
01535 }
01536
01537
01538
01539
01540
01541
01542
01543
01544 void
01545 FreeOverlappedLookasideList(
01546 )
01547 {
01548 WSAOVERLAPPEDPLUS *olp = NULL;
01549 LIST_ENTRY *entry = NULL;
01550
01551 EnterCriticalSection( &gOverlappedCS );
01552
01553 while ( ! IsListEmpty( &gFreeOverlappedPlus ) )
01554 {
01555 entry = RemoveHeadList( &gFreeOverlappedPlus );
01556
01557 olp = CONTAINING_RECORD( entry, WSAOVERLAPPEDPLUS, Link );
01558
01559 LspFree( olp );
01560 }
01561
01562 LeaveCriticalSection( &gOverlappedCS );
01563 }