home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / netds / winsock / nullprov / nullprov.cpp < prev    next >
C/C++ Source or Header  |  1997-10-08  |  18KB  |  797 lines

  1. /*++
  2.  
  3. Copyright 1996-1997 Microsoft Corporation
  4.  
  5. Copyright (c) 1996 Intel Corp
  6.  
  7. Module Name:
  8.  
  9.     nullprov.cpp
  10.  
  11. Abstract:
  12.  
  13.     This  module  provides  a  "null" provider for the purpose of demonstrating
  14.     what  it  takes  to  get  a  service  provider  installed and started.  The
  15.     provider pretty much does nothing but pretend to send and receive data.
  16.  
  17. --*/
  18.  
  19.  
  20. //
  21. // The Service Provider Interface was widened to Unicode in version 2.2.
  22. //  All of the parameters that involve strings in this module all provided
  23. //  in their "transparent" form.  They are switched to the wide character
  24. //  version, at compile time, by the following define:
  25. //
  26.  
  27. #define UNICODE
  28.  
  29. #include <windows.h>
  30. #include "ws2spi.h"
  31.  
  32. #include "nullpdef.h"
  33.  
  34.  
  35. // Global Upcall table with WinSock 2 DLL upcall entry points.
  36. WSPUPCALLTABLE g_upcalls;
  37.  
  38. // Global protocol info struct of the one protocol we support.
  39. WSAPROTOCOL_INFOA  g_protoinfo;
  40.  
  41.  
  42.  
  43.  
  44.  
  45.  
  46.  
  47. SOCKET WSPAPI WSPAccept(
  48.     SOCKET s,
  49.     struct sockaddr FAR * addr,
  50.     LPINT addrlen,
  51.     LPCONDITIONPROC lpfnCondition,
  52.     DWORD dwCallbackData,
  53.     LPINT lpErrno
  54.     )
  55. /*++
  56. --*/
  57. {
  58.     // Not implemented
  59.     return(INVALID_SOCKET);
  60. } // lpWSPAccept
  61.  
  62.  
  63.  
  64.  
  65. INT WSPAPI WSPAddressToString(
  66.     LPSOCKADDR lpsaAddress,
  67.     DWORD dwAddressLength,
  68.     LPWSAPROTOCOL_INFO lpProtocolInfo,
  69.     LPTSTR lpszAddressString,
  70.     LPDWORD lpdwAddressStringLength,
  71.     LPINT lpErrno
  72.     )
  73. /*++
  74. --*/
  75. {
  76.     // Not implemented
  77.     return(SOCKET_ERROR);
  78. } // lpWSPAddressToString
  79.  
  80.  
  81.  
  82.  
  83. int WSPAPI WSPAsyncSelect(
  84.     SOCKET s,
  85.     HWND hWnd,
  86.     unsigned int wMsg,
  87.     long lEvent,
  88.     LPINT lpErrno
  89.     )
  90. /*++
  91. --*/
  92. {
  93.     // Not implemented
  94.     return(SOCKET_ERROR);
  95. } // lpWSPAsyncSelect
  96.  
  97.  
  98.  
  99.  
  100. int WSPAPI WSPBind(
  101.     SOCKET s,
  102.     const struct sockaddr FAR * name,
  103.     int namelen,
  104.     LPINT lpErrno
  105.     )
  106. /*++
  107. Implementation:
  108.  
  109.     A  simple  implementation  is  supplied.  The implementation simply returns
  110.     success without really doing anything.
  111. --*/
  112. {
  113.     * lpErrno = ERROR_SUCCESS;
  114.     return(ERROR_SUCCESS);
  115.  
  116. } // lpWSPBind
  117.  
  118.  
  119.  
  120.  
  121. int WSPAPI WSPCancelBlockingCall(
  122.     LPINT lpErrno
  123.     )
  124. /*++
  125. Implementation:
  126.  
  127.     A  simple  implementation  is  supplied.  The implementation simply returns
  128.     success without really doing anything.
  129. --*/
  130. {
  131.     * lpErrno = ERROR_SUCCESS;
  132.     return(ERROR_SUCCESS);
  133.  
  134. } // lpWSPCancelBlockingCall
  135.  
  136.  
  137.  
  138.  
  139. int WSPAPI WSPCleanup(
  140.     LPINT lpErrno
  141.     )
  142. /*++
  143. Implementation
  144.  
  145.     A  simple  implementation  is  supplied.  The implementation simply returns
  146.     success  without  really  doing  anything.   This is technically incorrect,
  147.     since  we  should really maintain an up/down count of Startup/Cleanup pairs
  148.     and  return  an  error  code  if  WSPCleanup  is called when there is not a
  149.     WSPStartup outstanding.
  150. --*/
  151. {
  152.     * lpErrno = ERROR_SUCCESS;
  153.     return(ERROR_SUCCESS);
  154.  
  155. } // lpWSPCleanup
  156.  
  157.  
  158.  
  159.  
  160. int WSPAPI WSPCloseSocket(
  161.     SOCKET s,
  162.     LPINT lpErrno
  163.     )
  164. /*++
  165. Implementation
  166.  
  167.     Perform  an  upcall to the WinSock 2 DLL to inform it of the removal of the
  168.     socket handle.  Return the result.
  169. --*/
  170. {
  171.     int close_result;
  172.  
  173.     close_result = (* g_upcalls.lpWPUCloseSocketHandle)(
  174.         s,         // s
  175.         lpErrno);  // lpErrno
  176.     return(close_result);
  177.  
  178. } // lpWSPCloseSocket
  179.  
  180.  
  181.  
  182.  
  183. int WSPAPI WSPConnect(
  184.     SOCKET s,
  185.     const struct sockaddr FAR * name,
  186.     int namelen,
  187.     LPWSABUF lpCallerData,
  188.     LPWSABUF lpCalleeData,
  189.     LPQOS lpSQOS,
  190.     LPQOS lpGQOS,
  191.     LPINT lpErrno
  192.     )
  193. /*++
  194. Implementation
  195.  
  196.     A  simple implementation is supplied.  It indicates that no callee data was
  197.     retrieved and returns success.
  198. --*/
  199. {
  200.     if (lpCalleeData != NULL) {
  201.         lpCalleeData->len = 0;
  202.     }
  203.     * lpErrno = ERROR_SUCCESS;
  204.     return(ERROR_SUCCESS);
  205.  
  206. } // lpWSPConnect
  207.  
  208.  
  209.  
  210.  
  211. int WSPAPI WSPDuplicateSocket(
  212.     SOCKET s,
  213.     DWORD dwProcessId,
  214.     LPWSAPROTOCOL_INFO lpProtocolInfo,
  215.     LPINT lpErrno
  216.     )
  217. /*++
  218. --*/
  219. {
  220.     // Not implemented
  221.     return(SOCKET_ERROR);
  222. } // lpWSPDuplicateSocket
  223.  
  224.  
  225.  
  226.  
  227. int WSPAPI WSPEnumNetworkEvents(
  228.     SOCKET s,
  229.     WSAEVENT hEventObject,
  230.     LPWSANETWORKEVENTS lpNetworkEvents,
  231.     LPINT lpErrno
  232.     )
  233. /*++
  234. --*/
  235. {
  236.     // Not implemented
  237.     return(SOCKET_ERROR);
  238. } // lpWSPEnumNetworkEvents
  239.  
  240.  
  241.  
  242.  
  243. int WSPAPI WSPEventSelect(
  244.     SOCKET s,
  245.     WSAEVENT hEventObject,
  246.     long lNetworkEvents,
  247.     LPINT lpErrno
  248.     )
  249. /*++
  250. --*/
  251. {
  252.     // Not implemented
  253.     return(SOCKET_ERROR);
  254. } // lpWSPEventSelect
  255.  
  256.  
  257.  
  258.  
  259. int WSPAPI WSPGetOverlappedResult(
  260.     SOCKET s,
  261.     LPWSAOVERLAPPED lpOverlapped,
  262.     LPDWORD lpcbTransfer,
  263.     BOOL fWait,
  264.     LPDWORD lpdwFlags,
  265.     LPINT lpErrno
  266.     )
  267. /*++
  268. --*/
  269. {
  270.     // Not implemented
  271.     return(FALSE);
  272. } // lpWSPGetOverlappedResult
  273.  
  274.  
  275.  
  276.  
  277. int WSPAPI WSPGetPeerName(
  278.     SOCKET s,
  279.     struct sockaddr FAR * name,
  280.     LPINT namelen,
  281.     LPINT lpErrno
  282.     )
  283. /*++
  284. --*/
  285. {
  286.     // Not implemented
  287.     return(SOCKET_ERROR);
  288. } // lpWSPGetPeerName
  289.  
  290.  
  291.  
  292.  
  293. int WSPAPI WSPGetSockName(
  294.     SOCKET s,
  295.     struct sockaddr FAR * name,
  296.     LPINT namelen,
  297.     LPINT lpErrno
  298.     )
  299. /*++
  300. --*/
  301. {
  302.     // Not implemented
  303.     return(SOCKET_ERROR);
  304. } // lpWSPGetSockName
  305.  
  306.  
  307.  
  308.  
  309. int WSPAPI WSPGetSockOpt(
  310.     SOCKET s,
  311.     int level,
  312.     int optname,
  313.     char FAR * optval,
  314.     LPINT optlen,
  315.     LPINT lpErrno
  316.     )
  317. /*++
  318. --*/
  319. {
  320.     // Not implemented
  321.     return(SOCKET_ERROR);
  322. } // lpWSPGetSockOpt
  323.  
  324.  
  325.  
  326.  
  327. BOOL WSPAPI WSPGetQOSByName(
  328.     SOCKET s,
  329.     LPWSABUF lpQOSName,
  330.     LPQOS lpQOS,
  331.     LPINT lpErrno
  332.     )
  333. /*++
  334. --*/
  335. {
  336.     // Not implemented
  337.     return(FALSE);
  338. } // lpWSPGetQOSByName
  339.  
  340.  
  341.  
  342.  
  343. int WSPAPI WSPIoctl(
  344.     SOCKET s,
  345.     DWORD dwIoControlCode,
  346.     LPVOID lpvInBuffer,
  347.     DWORD cbInBuffer,
  348.     LPVOID lpvOutBuffer,
  349.     DWORD cbOutBuffer,
  350.     LPDWORD lpcbBytesReturned,
  351.     LPWSAOVERLAPPED lpOverlapped,
  352.     LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
  353.     LPWSATHREADID lpThreadId,
  354.     LPINT lpErrno
  355.     )
  356. /*++
  357. Not implemented,
  358. --*/
  359. {
  360.     // Not implemented
  361.     return(SOCKET_ERROR);
  362.  
  363. } // lpWSPIoctl
  364.  
  365.  
  366.  
  367.  
  368. SOCKET WSPAPI WSPJoinLeaf(
  369.     SOCKET s,
  370.     const struct sockaddr FAR * name,
  371.     int namelen,
  372.     LPWSABUF lpCallerData,
  373.     LPWSABUF lpCalleeData,
  374.     LPQOS lpSQOS,
  375.     LPQOS lpGQOS,
  376.     DWORD dwFlags,
  377.     LPINT lpErrno
  378.     )
  379. /*++
  380. --*/
  381. {
  382.     // Not implemented
  383.     return(INVALID_SOCKET);
  384. } // lpWSPJoinLeaf
  385.  
  386.  
  387.  
  388.  
  389. int WSPAPI WSPListen(
  390.     SOCKET s,
  391.     int backlog,
  392.     LPINT lpErrno
  393.     )
  394. /*++
  395. --*/
  396. {
  397.     // Not implemented
  398.     return(SOCKET_ERROR);
  399. } // lpWSPListen
  400.  
  401.  
  402.  
  403.  
  404. int WSPAPI WSPRecv(
  405.     SOCKET s,
  406.     LPWSABUF lpBuffers,
  407.     DWORD dwBufferCount,
  408.     LPDWORD lpNumberOfBytesRecvd,
  409.     LPDWORD lpFlags,
  410.     LPWSAOVERLAPPED lpOverlapped,
  411.     LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
  412.     LPWSATHREADID lpThreadId,
  413.     LPINT lpErrno
  414.     )
  415. /*++
  416. Implementation
  417.  
  418.     A  simple  implementation  is  supplied.   The  number of bytes received is
  419.     simply  filled  in as the number requested.  No actual data is deposited in
  420.     the  buffers.   The  client  will  "see"  whatever data happens to be there
  421.     already.
  422.  
  423.     This  simple implementation also violates the specification in that it does
  424.     not  support  overlapped  I/O.  It simply returns an error indication if an
  425.     attempt is made to use overlapped I/O features.
  426. --*/
  427. {
  428.     if ((lpOverlapped != NULL) ||
  429.         (lpCompletionRoutine != NULL)) {
  430.         // Overlapped I/O and its animal friends not implemented.
  431.         *lpErrno = WSAEINVAL;
  432.         return(SOCKET_ERROR);
  433.     }
  434.  
  435.     // Pretend to receive some data
  436.     * lpNumberOfBytesRecvd = lpBuffers[0].len;
  437.     * lpFlags = 0;
  438.     * lpErrno = ERROR_SUCCESS;
  439.     return(ERROR_SUCCESS);
  440.  
  441. } // lpWSPRecv
  442.  
  443.  
  444.  
  445.  
  446. int WSPAPI WSPRecvDisconnect(
  447.     SOCKET s,
  448.     LPWSABUF lpInboundDisconnectData,
  449.     LPINT lpErrno
  450.     )
  451. /*++
  452. --*/
  453. {
  454.     // Not implemented
  455.     return(SOCKET_ERROR);
  456. } // lpWSPRecvDisconnect
  457.  
  458.  
  459.  
  460.  
  461. int WSPAPI WSPRecvFrom(
  462.     SOCKET s,
  463.     LPWSABUF lpBuffers,
  464.     DWORD dwBufferCount,
  465.     LPDWORD lpNumberOfBytesRecvd,
  466.     LPDWORD lpFlags,
  467.     struct sockaddr FAR * lpFrom,
  468.     LPINT lpFromlen,
  469.     LPWSAOVERLAPPED lpOverlapped,
  470.     LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
  471.     LPWSATHREADID lpThreadId,
  472.     LPINT lpErrno
  473.     )
  474. /*++
  475. Implementation
  476.  
  477.     A  simple  implementation  is  supplied.   The  number of bytes received is
  478.     simply  filled  in as the number requested.  The "received from" address is
  479.     filled  in  with  a length of zero.  This might be an unexpected result, in
  480.     which case it could be changed to fill in some dummy constant address.
  481.  
  482.     This  simple implementation also violates the specification in that it does
  483.     not  support  overlapped  I/O.  It simply returns an error indication if an
  484.     attempt is made to use overlapped I/O features.
  485. --*/
  486. {
  487.     if ((lpOverlapped != NULL) ||
  488.         (lpCompletionRoutine != NULL)) {
  489.         // Overlapped I/O and its animal friends not implemented.
  490.         *lpErrno = WSAEINVAL;
  491.         return(SOCKET_ERROR);
  492.     }
  493.  
  494.     // Pretend to receive some data
  495.     * lpNumberOfBytesRecvd = lpBuffers[0].len;
  496.     * lpFlags = 0;
  497.     if (lpFromlen != NULL) {
  498.         * lpFromlen = 0;
  499.     }
  500.     * lpErrno = ERROR_SUCCESS;
  501.     return(ERROR_SUCCESS);
  502.  
  503. } // lpWSPRecvFrom
  504.  
  505.  
  506.  
  507.  
  508. int WSPAPI WSPSelect(
  509.     int nfds,
  510.     fd_set FAR * readfds,
  511.     fd_set FAR * writefds,
  512.     fd_set FAR * exceptfds,
  513.     const struct timeval FAR * timeout,
  514.     LPINT lpErrno
  515.     )
  516. /*++
  517. --*/
  518. {
  519.     // Not implemented
  520.     return(SOCKET_ERROR);
  521. } // lpWSPSelect
  522.  
  523.  
  524.  
  525.  
  526. int WSPAPI WSPSend(
  527.     SOCKET s,
  528.     LPWSABUF lpBuffers,
  529.     DWORD dwBufferCount,
  530.     LPDWORD lpNumberOfBytesSent,
  531.     DWORD dwFlags,
  532.     LPWSAOVERLAPPED lpOverlapped,
  533.     LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
  534.     LPWSATHREADID lpThreadId,
  535.     LPINT lpErrno
  536.     )
  537. /*++
  538. Implementation
  539.  
  540.     A  simple  implementation is supplied.  This implementation simply computes
  541.     the total number of bytes the client is attempting to send and fills in the
  542.     result to indicate that all the requested bytes were successfully sent.
  543.  
  544.     This  simple implementation also violates the specification in that it does
  545.     not  support  overlapped  I/O.  It simply returns an error indication if an
  546.     attempt is made to use overlapped I/O features.
  547. --*/
  548. {
  549.     DWORD bytes_sent;
  550.     DWORD buf_index;
  551.     
  552.     if ((lpOverlapped != NULL) ||
  553.         (lpCompletionRoutine != NULL)) {
  554.         // Overlapped I/O and its animal friends not implemented.
  555.         *lpErrno = WSAEINVAL;
  556.         return(SOCKET_ERROR);
  557.     }
  558.  
  559.     bytes_sent = 0;
  560.     for (buf_index = 0; buf_index < dwBufferCount; buf_index++) {
  561.         bytes_sent += lpBuffers[buf_index].len;
  562.     } // for buf_index
  563.     * lpNumberOfBytesSent = bytes_sent;
  564.     * lpErrno = ERROR_SUCCESS;
  565.     return(ERROR_SUCCESS);
  566.  
  567. } // lpWSPSend
  568.  
  569.  
  570.  
  571.  
  572. int WSPAPI WSPSendDisconnect(
  573.     SOCKET s,
  574.     LPWSABUF lpOutboundDisconnectData,
  575.     LPINT lpErrno
  576.     )
  577. /*++
  578. Implementation
  579.  
  580.     A  simple  implementation is supplied.  This implementation simply computes
  581.     the total number of bytes the client is attempting to send and fills in the
  582.     result to indicate that all the requested bytes were successfully sent.
  583.  
  584.     This  simple implementation also violates the specification in that it does
  585.     not  support  overlapped  I/O.  It simply returns an error indication if an
  586.     attempt is made to use overlapped I/O features.
  587. --*/
  588. {
  589.     // Not implemented
  590.     return(SOCKET_ERROR);
  591. } // lpWSPSendDisconnect
  592.  
  593.  
  594.  
  595.  
  596. int WSPAPI WSPSendTo(
  597.     SOCKET s,
  598.     LPWSABUF lpBuffers,
  599.     DWORD dwBufferCount,
  600.     LPDWORD lpNumberOfBytesSent,
  601.     DWORD dwFlags,
  602.     const struct sockaddr FAR * lpTo,
  603.     int iTolen,
  604.     LPWSAOVERLAPPED lpOverlapped,
  605.     LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
  606.     LPWSATHREADID lpThreadId,
  607.     LPINT lpErrno
  608.     )
  609. /*++
  610. --*/
  611. {
  612.     DWORD bytes_sent;
  613.     DWORD buf_index;
  614.     
  615.     if ((lpOverlapped != NULL) ||
  616.         (lpCompletionRoutine != NULL)) {
  617.         // Overlapped I/O and its animal friends not implemented.
  618.         *lpErrno = WSAEINVAL;
  619.         return(SOCKET_ERROR);
  620.     }
  621.  
  622.     bytes_sent = 0;
  623.     for (buf_index = 0; buf_index < dwBufferCount; buf_index++) {
  624.         bytes_sent += lpBuffers[buf_index].len;
  625.     } // for buf_index
  626.     * lpNumberOfBytesSent = bytes_sent;
  627.     * lpErrno = ERROR_SUCCESS;
  628.     return(ERROR_SUCCESS);
  629.     
  630. } // lpWSPSendTo
  631.  
  632.  
  633.  
  634.  
  635. int WSPAPI WSPSetSockOpt(
  636.     SOCKET s,
  637.     int level,
  638.     int optname,
  639.     const char FAR * optval,
  640.     int optlen,
  641.     LPINT lpErrno
  642.     )
  643. /*++
  644. --*/
  645. {
  646.     // Not implemented
  647.     return(SOCKET_ERROR);
  648. } // lpWSPSetSockOpt
  649.  
  650.  
  651.  
  652.  
  653. int WSPAPI WSPShutdown(
  654.     SOCKET s,
  655.     int how,
  656.     LPINT lpErrno
  657.     )
  658. /*++
  659. --*/
  660. {
  661.     // Not implemented
  662.     return(SOCKET_ERROR);
  663. } // lpWSPShutdown
  664.  
  665.  
  666.  
  667.  
  668. SOCKET WSPAPI WSPSocket(
  669.     int af,
  670.     int type,
  671.     int protocol,
  672.     LPWSAPROTOCOL_INFO lpProtocolInfo,
  673.     GROUP g,
  674.     DWORD dwFlags,
  675.     LPINT lpErrno
  676.     )
  677. /*++
  678. Implementation
  679.  
  680.     A  simple  implementation  is  supplied.   The procedure simply performs an
  681.     upcall  to  the  WinSock  2 DLL to allocate a socket handle.  The allocated
  682.     socket handle is returned as the new socket handle.
  683.  
  684.     Note that this implementation does not keep any state information about the
  685.     "socket"  it  allocated.   Consequently,  it simply uses 0 as the "context"
  686.     value  associated with the socket handle.  If it were desired to keep state
  687.     information  for  the  socket,  the  implementation  would  allocate a data
  688.     structure  to  store the state information, cast the data structure pointer
  689.     into a DWORD, and use this value as the dwContext.  When the implementation
  690.     needed    to    access    the    state    information,    it   would   call
  691.     WPUQuerySocketHandleContext  and  cast  the  retrieved  DWORD  back  to the
  692.     appropriate data structure pointer.
  693. --*/
  694. {
  695.     SOCKET  new_socket;
  696.  
  697.     new_socket = (* g_upcalls.lpWPUCreateSocketHandle)(
  698.         g_protoinfo.dwCatalogEntryId,  // dwCatalogEntryId
  699.         0,                             // dwContext
  700.         lpErrno);                      // lpErrno
  701.  
  702.     return(new_socket);
  703.  
  704. } // lpWSPSocket
  705.  
  706.  
  707.  
  708.  
  709. INT WSPAPI WSPStringToAddress(
  710.     LPTSTR AddressString,
  711.     INT AddressFamily,
  712.     LPWSAPROTOCOL_INFO lpProtocolInfo,
  713.     LPSOCKADDR lpAddress,
  714.     LPINT lpAddressLength,
  715.     LPINT     lpErrno
  716.     )
  717. /*++
  718. --*/
  719. {
  720.     // Not implemented
  721.     return(SOCKET_ERROR);
  722. } // lpWSPStringToAddress
  723.  
  724.  
  725.  
  726.  
  727. int WSPAPI WSPStartup(
  728.     WORD wVersionRequested,
  729.     LPWSPDATA lpWSPData,
  730.     LPWSAPROTOCOL_INFO lpProtocolInfo,
  731.     WSPUPCALLTABLE UpcallTable,
  732.     LPWSPPROC_TABLE lpProcTable
  733.     )
  734. /*++
  735. Implementation
  736.  
  737.     A  simple implementation is provided.  This just fills in required WSPData,
  738.     a  procedure  table,  and returns success.  Technically this implementation
  739.     violates  the  specification  since  it should maintain an up/down count of
  740.     WSPStartup/WSPCleanup pairs.
  741. --*/
  742. {
  743.     // Make  sure  that  the version requested is == 2.0 because that is all we
  744.     // support.
  745.     //
  746.     // The  low  byte  is  the  major  version  and  the high byte is the minor
  747.     // version.
  748.  
  749.     if ( LOBYTE( wVersionRequested ) < 2) {
  750.         return WSAVERNOTSUPPORTED;
  751.     }
  752.  
  753.     lpWSPData->wVersion = MAKEWORD( 2, 0 );
  754.     lpWSPData->wHighVersion = MAKEWORD( 2, 0 );
  755.  
  756. #define szDESCRIPTION "Null Provider for WinSock 2 preliminary sample source"
  757.     memcpy (lpWSPData->szDescription, szDESCRIPTION, sizeof szDESCRIPTION);
  758.  
  759.     memcpy (&g_protoinfo, lpProtocolInfo, sizeof WSAPROTOCOL_INFO);
  760.     
  761.     g_upcalls = UpcallTable;
  762.  
  763.     lpProcTable->lpWSPAccept = WSPAccept;
  764.     lpProcTable->lpWSPAddressToString = WSPAddressToString;
  765.     lpProcTable->lpWSPAsyncSelect = WSPAsyncSelect;
  766.     lpProcTable->lpWSPBind = WSPBind;
  767.     lpProcTable->lpWSPCancelBlockingCall = WSPCancelBlockingCall;
  768.     lpProcTable->lpWSPCleanup = WSPCleanup;
  769.     lpProcTable->lpWSPCloseSocket = WSPCloseSocket;
  770.     lpProcTable->lpWSPConnect = WSPConnect;
  771.     lpProcTable->lpWSPDuplicateSocket = WSPDuplicateSocket;
  772.     lpProcTable->lpWSPEnumNetworkEvents = WSPEnumNetworkEvents;
  773.     lpProcTable->lpWSPEventSelect = WSPEventSelect;
  774.     lpProcTable->lpWSPGetOverlappedResult = WSPGetOverlappedResult;
  775.     lpProcTable->lpWSPGetPeerName = WSPGetPeerName;
  776.     lpProcTable->lpWSPGetSockName = WSPGetSockName;
  777.     lpProcTable->lpWSPGetSockOpt = WSPGetSockOpt;
  778.     lpProcTable->lpWSPGetQOSByName = WSPGetQOSByName;
  779.     lpProcTable->lpWSPIoctl = WSPIoctl;
  780.     lpProcTable->lpWSPJoinLeaf = WSPJoinLeaf;
  781.     lpProcTable->lpWSPListen = WSPListen;
  782.     lpProcTable->lpWSPRecv = WSPRecv;
  783.     lpProcTable->lpWSPRecvDisconnect = WSPRecvDisconnect;
  784.     lpProcTable->lpWSPRecvFrom = WSPRecvFrom;
  785.     lpProcTable->lpWSPSelect = WSPSelect;
  786.     lpProcTable->lpWSPSend = WSPSend;
  787.     lpProcTable->lpWSPSendDisconnect = WSPSendDisconnect;
  788.     lpProcTable->lpWSPSendTo = WSPSendTo;
  789.     lpProcTable->lpWSPSetSockOpt = WSPSetSockOpt;
  790.     lpProcTable->lpWSPShutdown = WSPShutdown;
  791.     lpProcTable->lpWSPSocket = WSPSocket;
  792.     lpProcTable->lpWSPStringToAddress = WSPStringToAddress;
  793.  
  794.     return(ERROR_SUCCESS);
  795.     
  796. } // WSPStartup
  797.