home *** CD-ROM | disk | FTP | other *** search
/ What PC? 1996 April / WHAT_PC_APR_96.ISO / internet / twinsock / src / winsock.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-23  |  55.8 KB  |  2,390 lines

  1. /*
  2.  *  TwinSock - "Troy's Windows Sockets"
  3.  *
  4.  *  Copyright (C) 1994-1995  Troy Rollo <troy@cbme.unsw.EDU.AU>
  5.  *
  6.  *  This program is free software; you can redistribute it and/or modify
  7.  *  it under the terms of the license in the file LICENSE.TXT included
  8.  *  with the TwinSock distribution.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
  13.  */
  14.  
  15. #include <winsock.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <stdio.h>
  19. #include <dos.h>
  20. #include "twinsock.h"
  21. #include "tx.h"
  22.  
  23. #ifdef __MSDOS__
  24. #define    PORTSWAP(x)    ntohs(x)
  25. #else
  26. #define    PORTSWAP(x)    ntohl(x)
  27. #endif
  28.  
  29. static    int    iErrno = 0;
  30. static    short    idNext = 0;
  31.  
  32. static    struct    per_task    *pptList = 0;
  33. static    struct    per_socket    *ppsList = 0;
  34. static    struct    tx_queue    *ptxqList = 0;
  35.  
  36. HWND    hwndManager = 0;
  37. BOOL    bEstablished = 0;
  38.  
  39. static    void    FireAsyncRequest(struct tx_queue *ptxq);
  40.  
  41. int FAR PASCAL
  42. LibMain(HINSTANCE hInst, WORD wOne, WORD wTwo, LPSTR lpstr)
  43. {
  44.     return TRUE;
  45. }
  46.  
  47. void far pascal _export
  48. RegisterManager(HWND hwnd)
  49. {
  50.     hwndManager = hwnd;
  51. }
  52.  
  53. void far pascal _export
  54. SetInitialised(void)
  55. {
  56.     bEstablished = TRUE;
  57. }
  58.  
  59.  
  60. void
  61. CopyDataIn(    void        *pvSource,
  62.         enum arg_type    at,
  63.         void        *pvDest,
  64.         int        nLen)
  65. {
  66.     switch(at)
  67.     {
  68.     case AT_Int16:
  69.     case AT_Int16Ptr:
  70.         *(short *) pvDest = ntohs(*(short *) pvSource);
  71.         break;
  72.  
  73.     case AT_Int32:
  74.     case AT_Int32Ptr:
  75.         *(long *) pvDest = ntohl(*(long *) pvSource);
  76.         break;
  77.  
  78.     case AT_Char:
  79.         *(char *) pvDest = *(char *) pvSource;
  80.         break;
  81.  
  82.     case AT_GenPtr:
  83.     case AT_String:
  84.         memcpy(pvDest, pvSource, nLen);
  85.         break;
  86.     }
  87. }
  88.  
  89. void
  90. CopyDataOut(    void        *pvDest,
  91.         enum arg_type    at,
  92.         void        *pvSource,
  93.         int        nLen)
  94. {
  95.     switch(at)
  96.     {
  97.     case AT_Int16Ptr:
  98.     case AT_Int16:
  99.         *(short *) pvDest = htons(*(short *) pvSource);
  100.         break;
  101.  
  102.     case AT_Int32:
  103.     case AT_Int32Ptr:
  104.         *(long *) pvDest = htonl(*(long *) pvSource);
  105.         break;
  106.  
  107.     case AT_Char:
  108.         *(char *) pvDest = *(char *) pvSource;
  109.         break;
  110.  
  111.     case AT_GenPtr:
  112.     case AT_String:
  113.         memcpy(pvDest, pvSource, nLen);
  114.         break;
  115.     }
  116. }
  117.  
  118. static    struct    per_task *
  119. GetAnotherTaskInfo(HTASK htask)
  120. {
  121.     struct per_task *ppt;
  122.  
  123.     for (ppt = pptList; ppt; ppt = ppt->pptNext)
  124.     {
  125.         if (ppt->htask == htask)
  126.             return ppt;
  127.     }
  128.     iErrno = WSANOTINITIALISED;
  129.     return 0;
  130. }
  131.  
  132. static    struct    per_task *
  133. GetTaskInfo(void)
  134. {
  135.     return GetAnotherTaskInfo(GetCurrentTask());
  136. }
  137.  
  138.  
  139. static    struct    per_socket *
  140. GetSocketInfo(SOCKET s)
  141. {
  142.     struct per_socket *pps;
  143.  
  144.  
  145.     for (pps = ppsList; pps; pps = pps->ppsNext)
  146.     {
  147.         if (pps->s == s)
  148.             return pps;
  149.     }
  150.     iErrno = WSAENOTSOCK;
  151.     return 0;
  152. }
  153.  
  154. static    void
  155. Notify(struct per_socket *pps,
  156.     int iCode)
  157. {
  158.     if (pps->iEvents & iCode)
  159.         PostMessage(pps->hWnd, pps->wMsg, pps->s, WSAMAKESELECTREPLY(iCode, 0));
  160. }
  161.  
  162. static    void
  163. NotifyError(    struct per_socket *pps,
  164.         int    iCode,
  165.         int    iErrno)
  166. {
  167.     if (pps->iEvents & iCode)
  168.         PostMessage(pps->hWnd, pps->wMsg, pps->s, WSAMAKESELECTREPLY(iCode, iErrno));
  169. }
  170.  
  171. static    struct    per_socket *
  172. NewSocket(struct per_task *ppt, SOCKET s)
  173. {
  174.     struct per_socket *ppsNew;
  175.  
  176.     ppsNew = (struct per_socket *) malloc(sizeof(struct per_socket));
  177.     if (ppsNew == 0)
  178.         return (ppsNew);
  179.     ppsNew->s = s;
  180.     ppsNew->iFlags = 0;
  181.     ppsNew->pdIn = 0;
  182.     ppsNew->pdOut = 0;
  183.     ppsNew->htaskOwner = ppt->htask;
  184.     ppsNew->ppsNext = ppsList;
  185.     ppsNew->iEvents = 0;
  186.     ppsNew->nOutstanding = 0;
  187.     ppsList = ppsNew;
  188.     return ppsNew;
  189.     
  190. }
  191.  
  192. static void SendEarlyClose(SOCKET s);
  193.  
  194. static    void
  195. RemoveSocket(struct per_socket *pps)
  196. {
  197.     struct    per_socket **ppps, *ppsParent;
  198.     struct    data    **ppd, *pd;
  199.  
  200.     /* If our parent has noticed we're here, we need to remove ourselves
  201.      * from the list of sockets awaiting acception.
  202.      */
  203.     for (ppsParent = ppsList; ppsParent; ppsParent = ppsParent->ppsNext)
  204.     {
  205.         if (!(ppsParent->iFlags & PSF_ACCEPT))
  206.             continue;
  207.         for (ppd = &ppsParent->pdIn; *ppd; ppd = &(*ppd)->pdNext)
  208.         {
  209.             if ((*ppd)->pchData == (char *) pps)
  210.             {
  211.                 pd = *ppd;
  212.                 *ppd = pd->pdNext;
  213.                 free(pd);
  214.             }
  215.         }
  216.     }
  217.  
  218.     /* Find our own position in the list */
  219.     for (ppps = &ppsList; *ppps; ppps = &(*ppps)->ppsNext)
  220.     {
  221.         if (*ppps == pps)
  222.         {
  223.             *ppps = pps->ppsNext;
  224.  
  225.             /* If we have unacknowledged children, kill them */
  226.             while (pps->pdIn)
  227.             {
  228.                 pd = pps->pdIn;
  229.                 pps->pdIn = pd->pdNext;
  230.                 if (pps->iFlags & PSF_ACCEPT)
  231.                 {
  232.                     SendEarlyClose(((struct per_socket *) pd->pchData)->s);
  233.                     RemoveSocket((struct per_socket *) pd->pchData);
  234.                 }
  235.                 else
  236.                 {
  237.                     free(pd->pchData);
  238.                 }
  239.                 free(pd);
  240.             }
  241.             free(pps);
  242.             return;
  243.         }
  244.     }
  245. }
  246.  
  247. static    void
  248. FunctionReceived(SOCKET s, void *pvData, int nLen, enum Functions ft)
  249. {
  250.     struct    data    *pdNew, **ppdList;
  251.     struct    per_socket *pps, *ppsNew;
  252.     struct    per_task *ppt;
  253.     int        ns;
  254.  
  255.     pps = GetSocketInfo(s);
  256.     if (!pps)
  257.     {
  258.         if (ft == FN_Accept)
  259.         {
  260.             nLen -= sizeof(struct sockaddr_in);
  261.             pvData = (char *) pvData + sizeof(struct sockaddr_in);
  262.             if (nLen == sizeof(long))
  263.                 ns = (int) ntohl(*(long *) pvData);
  264.             else
  265.                 ns = (int) ntohs(*(short*) pvData);
  266.             SendEarlyClose(ns);
  267.         }
  268.         return;
  269.     }
  270.     for (ppdList = &pps->pdIn; *ppdList; ppdList = &(*ppdList)->pdNext);
  271.  
  272.     pdNew = (struct data *) malloc(sizeof(struct data));
  273.     if (pdNew == 0)
  274.         return; /* We will get out of sync, but such is life */
  275.     pdNew->sin = *(struct sockaddr_in *) pvData;
  276.     pdNew->sin.sin_family = ntohs(pdNew->sin.sin_family);
  277.  
  278.     nLen -= sizeof(struct sockaddr_in);
  279.     pvData = (char *) pvData + sizeof(struct sockaddr_in);
  280.  
  281.     pdNew->pdNext = 0;
  282.     pdNew->nUsed = 0;
  283.     *ppdList = pdNew;
  284.  
  285.     /* Note that the calls to Notify below should *really*
  286.      * only be made if the data gets put at the head of the
  287.      * queue, but some telnet implementations miss notifications
  288.      * and this screws us right up. By putting in additional
  289.      * notifications we at least have a chance of recovery.
  290.      */
  291.     if (pps->iFlags & PSF_ACCEPT)
  292.     {
  293.         pdNew->iLen = 0;
  294.         if (nLen == sizeof(long))
  295.             ns = (int) ntohl(*(long *) pvData);
  296.         else
  297.             ns = (int) ntohs(*(short*) pvData);
  298.         ppt = GetAnotherTaskInfo(pps->htaskOwner);
  299.         ppsNew = NewSocket(ppt, ns);
  300.         pdNew->pchData = (char *) ppsNew;
  301.         ppsNew->iFlags |= PSF_CONNECT;
  302.         Notify(pps, FD_ACCEPT);
  303.     }
  304.     else
  305.     {
  306.         pdNew->iLen = nLen;
  307.         pdNew->pchData = (char *) malloc(nLen);
  308.         if (pdNew->pchData == 0)
  309.         {
  310.             pdNew->iLen = 0;    /* Return EOF to the application */
  311.             return;
  312.         }
  313.         memcpy(pdNew->pchData, pvData, nLen);
  314.         Notify(pps, nLen ? FD_READ : FD_CLOSE);
  315.     }
  316. }
  317.  
  318. static    BOOL
  319. StartBlocking(struct per_task *ppt)
  320. {
  321.     if (ppt->bBlocking)
  322.     {
  323.         iErrno = WSAEINPROGRESS;
  324.         return FALSE;
  325.     }
  326.     else
  327.     {
  328.         ppt->bBlocking = TRUE;
  329.         ppt->bCancel = FALSE;
  330.         return TRUE;
  331.     }
  332. }
  333.  
  334. static    void
  335. EndBlocking(struct per_task *ppt)
  336. {
  337.     ppt->bBlocking = FALSE;
  338. }
  339.  
  340. static    BOOL
  341. FlushMessages(struct per_task *ppt)
  342. {
  343.     MSG msg;
  344.     BOOL ret;
  345.  
  346.     if (ppt->lpBlockFunc)
  347.         return ((BOOL (far pascal *)()) ppt->lpBlockFunc)();
  348.  
  349.      ret = (BOOL) PeekMessage(&msg,0,0,0,PM_REMOVE);
  350.     if (ret)
  351.     {
  352.         TranslateMessage(&msg);
  353.         DispatchMessage(&msg);
  354.         /* Some poorly behaved applications quit without
  355.          * checking the return value of WSACancel. It
  356.          * *can* fail.
  357.          */
  358.         if (msg.message == WM_QUIT)
  359.             ppt->bCancel = TRUE;
  360.     }
  361.     return ret;
  362. }
  363.  
  364. static    void
  365. RemoveTXQ(struct tx_queue *ptxq)
  366. {
  367.     struct    tx_queue **pptxq;
  368.  
  369.     for (pptxq = &ptxqList; *pptxq; pptxq = &((*pptxq)->ptxqNext))
  370.     {
  371.         if (*pptxq == ptxq)
  372.         {
  373.             *pptxq = ptxq->ptxqNext;
  374.             free(ptxq->ptxr);
  375.             free(ptxq);
  376.             return;
  377.         }
  378.     }
  379. }
  380.  
  381. static    void
  382. RemoveTask(struct per_task *ppt)
  383. {
  384.     struct per_task **pppt;
  385.  
  386.     for (pppt = &pptList; *pppt; pppt = &((*pppt)->pptNext))
  387.     {
  388.         if (*pppt == ppt)
  389.         {
  390.             *pppt = ppt->pptNext;
  391.             free(ppt);
  392.             break;
  393.         }
  394.     }
  395. };
  396.  
  397. void far pascal _export
  398. ResponseReceived(struct tx_request *ptxr)
  399. {
  400.     int        nLen;
  401.     int        id;
  402.     struct    tx_queue *ptxq;
  403.     enum Functions    ft;
  404.  
  405.     ft = (enum Functions) ntohs(ptxr->iType);
  406.     id = ntohs(ptxr->id);
  407.     nLen = ntohs(ptxr->nLen);
  408.     if (ft == FN_Data || ft == FN_Accept)
  409.     {
  410.         FunctionReceived(id, ptxr->pchData, nLen - sizeof(short) * 5, ft);
  411.         return;
  412.     }
  413.     for (ptxq = ptxqList; ptxq; ptxq = ptxq->ptxqNext)
  414.     {
  415.         if (ptxq->id == id)
  416.         {
  417.             memcpy(ptxq->ptxr, ptxr, nLen);
  418.             ptxq->bDone = TRUE;
  419.             if (ptxq->pchLocation)
  420.                 FireAsyncRequest(ptxq);
  421.             return;
  422.         }
  423.     }
  424.     if (ft == FN_SendTo || ft == FN_Send || ft == FN_Connect)
  425.     {
  426.         int    iOffset = 0;
  427.         int    iLen;
  428.         enum arg_type at;
  429.         long    nValue;
  430.         struct    per_socket *pps;
  431.         int    i;
  432.         int    nCode;
  433.  
  434.         switch(ft)
  435.         {
  436.         case FN_SendTo:
  437.         case FN_Send:
  438.             nCode = 2;
  439.             break;
  440.  
  441.         case FN_Connect:
  442.             nCode = 3;
  443.             break;
  444.         }
  445.  
  446.         for (i = 0; i <= nCode; i++)
  447.         {
  448.             at = (enum arg_type) ntohs(*(short *) (ptxr->pchData + iOffset));
  449.             iOffset += 2;
  450.             iLen = ntohs(*(short *) (ptxr->pchData + iOffset));
  451.             iOffset += 2;
  452.             if (i == 0 || i == nCode)
  453.             {
  454.                 if (at == AT_Int16)
  455.                     nValue = ntohs(*(short *) (ptxr->pchData + iOffset));
  456.                 else
  457.                     nValue = ntohl(*(long *) (ptxr->pchData + iOffset));
  458.                 if (i == 0)
  459.                 {
  460.                     pps = GetSocketInfo(nValue);
  461.                     if (!pps)
  462.                         return;
  463.                 }
  464.                 else if (ft == FN_Connect)
  465.                 {
  466.                     if (nValue < 0)
  467.                     {
  468.                         NotifyError(pps, FD_CONNECT, ntohs(ptxr->nError));
  469.                     }
  470.                     else
  471.                     {
  472.                         pps->iFlags |= PSF_CONNECT;
  473.                         Notify(pps, FD_CONNECT);
  474.                         Notify(pps, FD_WRITE);
  475.                     }
  476.                 }
  477.                 else
  478.                 {
  479.                     if (nValue < 0)
  480.                     {
  481.                         pps->nOutstanding = 0;
  482.                         NotifyError(pps, FD_WRITE, ntohs(ptxr->nError));
  483.                     }    
  484.                     else
  485.                     {
  486.                         pps->nOutstanding -= nValue;
  487.                         if (pps->nOutstanding < MAX_OUTSTANDING)
  488.                             Notify(pps, FD_WRITE);
  489.                     }
  490.                 }
  491.             }
  492.             iOffset += iLen;
  493.         }
  494.     }
  495. }
  496.  
  497. static    struct tx_queue *
  498. TransmitFunction(struct transmit_function *ptf)
  499. {
  500.     int    i;
  501.     int    nSize = sizeof(short) * 5;
  502.     struct    tx_request *ptxr;
  503.     struct    tx_queue *ptxq, **pptxq;
  504.     int    iOffset;
  505.  
  506.     for (i = 0; i < ptf->nArgs; i++)
  507.         nSize += ptf->pfaList[i].iLen + sizeof(short) * 2;
  508.     nSize += ptf->pfaResult->iLen + sizeof(short) * 2;
  509.     ptxr = (struct tx_request *) malloc(nSize);
  510.     if (ptxr == 0)
  511.     {
  512.         return 0;
  513.     }
  514.     ptxr->iType = htons((short) ptf->fn);
  515.     ptxr->nArgs = htons((short) ptf->nArgs);
  516.     ptxr->nError = 0;
  517.     ptxr->nLen = htons((short) nSize);
  518.     ptxr->id = htons(idNext);
  519.     for (iOffset = i = 0; i < ptf->nArgs; i++)
  520.     {
  521.         *(short *) (ptxr->pchData + iOffset) = htons((short) ptf->pfaList[i].at);
  522.         iOffset += 2;
  523.         *(short *) (ptxr->pchData + iOffset) = htons((short) ptf->pfaList[i].iLen);
  524.         iOffset += 2;
  525.         CopyDataOut(    ptxr->pchData + iOffset,
  526.                 ptf->pfaList[i].at,
  527.                 ptf->pfaList[i].pvData,
  528.                 ptf->pfaList[i].iLen);
  529.         iOffset += ptf->pfaList[i].iLen;
  530.     }
  531.     *(short *) (ptxr->pchData + iOffset) = htons((short) ptf->pfaResult->at);
  532.     iOffset += 2;
  533.     *(short *) (ptxr->pchData + iOffset) = htons((short) ptf->pfaResult->iLen);
  534.     iOffset += 2;
  535.     CopyDataOut(    ptxr->pchData + iOffset,
  536.             ptf->pfaResult->at,
  537.             ptf->pfaResult->pvData,
  538.             ptf->pfaResult->iLen);
  539.  
  540.     iOffset += ptf->pfaResult->iLen;
  541.  
  542.     ptxq = (struct tx_queue *) malloc(sizeof(struct tx_queue));
  543.     if (ptxq == 0)
  544.     {
  545.         free(ptxr);
  546.         return 0;
  547.     }
  548.     ptxq->ptxqNext = 0;
  549.     ptxq->id = idNext;
  550.     ptxq->ptxr = ptxr;
  551.     ptxq->bDone = 0;
  552.     ptxq->hwnd = 0;
  553.     ptxq->pchLocation = 0;
  554.     ptxq->wMsg = 0;
  555.     idNext++;
  556.     for (pptxq = &ptxqList; *pptxq; pptxq = &((*pptxq)->ptxqNext));
  557.     *pptxq = ptxq;
  558.     SendMessage(hwndManager, WM_USER, nSize, (LPARAM) ptxr);
  559.     return ptxq;
  560. };
  561.  
  562. static void
  563. SendEarlyClose(SOCKET s)
  564. {
  565.     struct    func_arg pfaArgs[1];
  566.     struct    func_arg pfaReturn;
  567.     struct    transmit_function tf;
  568.     int    nReturn;
  569.  
  570.     INIT_ARGS(pfaArgs[0],    AT_Int,        &s,        sizeof(s)        );
  571.     INIT_ARGS(pfaReturn,    AT_Int,        &nReturn,    sizeof(nReturn)        );
  572.     INIT_TF(tf, FN_Close, 1, pfaArgs, pfaReturn);
  573.     RemoveTXQ(TransmitFunction(&tf));
  574. }
  575.  
  576. static void
  577. SetErrorResult(struct func_arg *pfaResult)
  578. {
  579.     switch (pfaResult->at)
  580.     {
  581.     case AT_Int16:
  582.         *(short *) pfaResult->pvData = -1;
  583.         break;
  584.  
  585.     case AT_Int32:
  586.         *(long *) pfaResult->pvData = -1;
  587.         break;
  588.  
  589.     case AT_Char:
  590.         *(char *) pfaResult->pvData = -1;
  591.         break;
  592.  
  593.     case AT_Int16Ptr:
  594.     case AT_Int32Ptr:
  595.     case AT_String:
  596.     case AT_GenPtr:
  597.         *(void **) pfaResult->pvData = 0;
  598.         break;
  599.     }
  600. }
  601.  
  602. static    int    TransmitFunctionAndBlock(
  603.             struct per_task *ppt,
  604.             struct transmit_function *ptf)
  605. {
  606.     struct tx_queue *ptxq;
  607.     struct tx_request *ptxr;
  608.     int    i, iOffset;
  609.     BOOL    bError = FALSE;
  610.  
  611.     if (!StartBlocking(ppt))
  612.     {
  613.         iErrno = WSAEINPROGRESS;
  614.         SetErrorResult(ptf->pfaResult);
  615.         return 0;
  616.     }
  617.     ptxq = TransmitFunction(ptf);
  618.     ptxr = ptxq->ptxr;
  619.     while (!ptxq->bDone)
  620.     {
  621.         FlushMessages(ppt);
  622.         if (ppt->bCancel)
  623.         {
  624.             iErrno = WSAEINTR;
  625.             RemoveTXQ(ptxq);
  626.             SetErrorResult(ptf->pfaResult);
  627.             EndBlocking(ppt);
  628.             return 0;
  629.         }
  630.     }
  631.     if (ptxq->ptxr->nError)
  632.     {
  633.         iErrno = ntohs(ptxq->ptxr->nError);
  634.         SetErrorResult(ptf->pfaResult);
  635.         bError = TRUE;
  636.     }
  637.     else
  638.     {
  639.         for (iOffset = i = 0; i < ptf->nArgs; i++)
  640.         {
  641.             ptf->pfaList[i].at = (enum arg_type) ntohs(*(short *) (ptxr->pchData + iOffset));
  642.             iOffset += 2;
  643.             ptf->pfaList[i].iLen = ntohs(*(short *) (ptxr->pchData + iOffset));
  644.             iOffset += 2;
  645.             if (!ptf->pfaList[i].bConstant)
  646.                 CopyDataIn(    ptxr->pchData + iOffset,
  647.                         ptf->pfaList[i].at,
  648.                         ptf->pfaList[i].pvData,
  649.                         ptf->pfaList[i].iLen);
  650.             iOffset += ptf->pfaList[i].iLen;
  651.         }
  652.         ptf->pfaResult->at = (enum arg_type) ntohs(*(short *) (ptxr->pchData + iOffset));
  653.         iOffset += 2;
  654.         ptf->pfaResult->iLen = ntohs(*(short *) (ptxr->pchData + iOffset));
  655.         iOffset += 2;
  656.         CopyDataIn(    ptxr->pchData + iOffset,
  657.                 ptf->pfaResult->at,
  658.                 ptf->pfaResult->pvData,
  659.                 ptf->pfaResult->iLen);
  660.  
  661.     }
  662.     RemoveTXQ(ptxq);
  663.     EndBlocking(ppt);
  664.     return bError ? 0 : 1;
  665. }
  666.  
  667. static void
  668. CopyHostEnt(struct per_task *ppt)
  669. {
  670.     int    iLocation;
  671.     int    i;
  672.     int    nAddrs;
  673.  
  674.     ppt->he.h_addrtype = ntohs(*(short *) ppt->achHostEnt);
  675.     ppt->he.h_length = ntohs(*(short *) (ppt->achHostEnt + sizeof(short)));
  676.     nAddrs = ntohs(*(short *) (ppt->achHostEnt + sizeof(short) * 2));
  677.     iLocation = sizeof(short) * 3;
  678.     for (i = 0; i < nAddrs; i++)
  679.     {
  680.         if (i < MAX_ALTERNATES - 1)
  681.             ppt->apchHostAddresses[i] = ppt->achHostEnt + iLocation;
  682.         iLocation += 4;
  683.     }
  684.     if (nAddrs < MAX_ALTERNATES - 1)
  685.         ppt->apchHostAddresses[nAddrs] = 0;
  686.     else
  687.         ppt->apchHostAddresses[MAX_ALTERNATES - 1] = 0;
  688.     ppt->he.h_addr_list = ppt->apchHostAddresses;
  689.     ppt->he.h_name = ppt->achHostEnt + iLocation;
  690.     iLocation += strlen(ppt->achHostEnt + iLocation)+ 1;
  691.     for (i = 0; ppt->achHostEnt[iLocation] && i < MAX_ALTERNATES - 1; i++)
  692.     {
  693.         ppt->apchHostAlii[i] = ppt->achHostEnt + iLocation;
  694.         iLocation += strlen(ppt->achHostEnt + iLocation)+ 1;
  695.     }
  696.     ppt->apchHostAlii[i] = 0;
  697.     ppt->he.h_aliases = ppt->apchHostAlii;
  698.     ppt->he.h_addr_list = ppt->apchHostAddresses;
  699. }
  700.  
  701. static int
  702. CopyHostEntTo(struct per_task *ppt, char *pchData)
  703. {
  704.     int    i;
  705.     int    nAddrs;
  706.     struct hostent *phe;
  707.     char    *pchOld;
  708.     int    nAlii;
  709.  
  710.     CopyHostEnt(ppt);
  711.  
  712.     phe = (struct hostent *) pchData;
  713.     memcpy(phe, &ppt->he, sizeof(ppt->he));
  714.  
  715.     pchData += sizeof(*phe);
  716.  
  717.     for (nAddrs = 0; phe->h_addr_list[nAddrs]; nAddrs++);
  718.     for (nAlii = 0; phe->h_aliases[nAlii]; nAlii++);
  719.  
  720.     memcpy(pchData, phe->h_addr_list, sizeof(char *) * (nAddrs + 1));
  721.     phe->h_addr_list = (char **) pchData;
  722.     pchData += sizeof(char *) * (nAddrs + 1);
  723.  
  724.     memcpy(pchData, phe->h_aliases, sizeof(char *) * (nAddrs + 1));
  725.     phe->h_aliases = (char **) pchData;
  726.     pchData += sizeof(char *) * (nAddrs + 1);
  727.  
  728.     pchOld = phe->h_addr_list[0];
  729.     memcpy(pchData, pchOld, 4 * nAddrs);
  730.     for (i = 0; i < nAddrs; i++)
  731.         phe->h_addr_list[i] =  pchData + (phe->h_addr_list[i] - pchOld);
  732.     pchData += 4 * nAddrs;
  733.  
  734.     strcpy(pchData, phe->h_name);
  735.     phe->h_name = pchData;
  736.     pchData += strlen(pchData) + 1;
  737.  
  738.     for (i = 0; i < nAlii; i++)
  739.     {
  740.         strcpy(pchData, phe->h_aliases[i]);
  741.         phe->h_aliases[i] = pchData;
  742.         pchData += strlen(pchData) + 1;
  743.     }
  744.     return (pchData - (char *) phe);
  745. }
  746.  
  747. static void
  748. CopyServEnt(struct per_task *ppt)
  749. {
  750.     int    iLocation;
  751.     int    i;
  752.  
  753.     /* Note that s_port is needed in network byte order */
  754.         ppt->se.s_port = *(short *) ppt->achServEnt;
  755.     iLocation = sizeof(short);
  756.     ppt->se.s_proto = ppt->achServEnt + iLocation;
  757.     iLocation += strlen(ppt->achServEnt + iLocation) + 1;
  758.     ppt->se.s_name = ppt->achServEnt + iLocation;
  759.     iLocation += strlen(ppt->achServEnt + iLocation) + 1;
  760.     for (i = 0; ppt->achServEnt[iLocation] && i < MAX_ALTERNATES - 1; i++)
  761.     {
  762.         ppt->apchServAlii[i] = ppt->achServEnt + iLocation;
  763.         iLocation += strlen(ppt->achServEnt + iLocation) + 1;
  764.     }
  765.     ppt->apchServAlii[i] = 0;
  766.     ppt->se.s_aliases = ppt->apchServAlii;
  767. }
  768.  
  769. static int
  770. CopyServEntTo(struct per_task *ppt, char *pchData)
  771. {
  772.     int    i;
  773.     int    nAlii;
  774.     struct    servent *pse;
  775.  
  776.     CopyServEnt(ppt);
  777.  
  778.     pse = (struct servent *) pchData;
  779.     memcpy(pse, &ppt->se, sizeof(ppt->se));
  780.     pchData += sizeof(*pse);
  781.  
  782.     for (nAlii = 0; pse->s_aliases[nAlii]; nAlii++);
  783.     memcpy(pchData, pse->s_aliases, sizeof(char *) * (nAlii + 1));
  784.     pse->s_aliases = (char **) pchData;
  785.     pchData += sizeof(char *) * (nAlii + 1);
  786.  
  787.     strcpy(pchData, ppt->se.s_name);
  788.     ppt->se.s_name = pchData;
  789.     pchData += strlen(pchData) + 1;
  790.  
  791.     strcpy(pchData, ppt->se.s_proto);
  792.     ppt->se.s_proto = pchData;
  793.     pchData += strlen(pchData) + 1;
  794.  
  795.     for (i = 0; i < nAlii; i++)
  796.     {
  797.         strcpy(pchData, pse->s_aliases[i]);
  798.         pse->s_aliases[i] = pchData;
  799.         pchData += strlen(pchData) + 1;
  800.     }
  801.     return (pchData - (char *) pse);
  802. }
  803.  
  804. static void
  805. CopyProtoEnt(struct per_task *ppt)
  806. {
  807.     int    iLocation;
  808.     int    i;
  809.  
  810.     ppt->pe.p_proto = ntohs(*(short *) ppt->achProtoEnt);
  811.     iLocation = sizeof(short);
  812.     ppt->pe.p_name = ppt->achProtoEnt + iLocation;
  813.     iLocation += strlen(ppt->achProtoEnt + iLocation) + 1;
  814.     for (i = 0; ppt->achProtoEnt[iLocation] && i < MAX_ALTERNATES - 1; i++)
  815.     {
  816.         ppt->apchProtoAlii[i] = ppt->achProtoEnt + iLocation;
  817.         iLocation += strlen(ppt->achProtoEnt + iLocation) + 1;
  818.     }
  819.     ppt->apchProtoAlii[i] = 0;
  820.     ppt->pe.p_aliases = ppt->apchProtoAlii;
  821. }
  822.  
  823. static int
  824. CopyProtoEntTo(struct per_task *ppt, char *pchData)
  825. {
  826.     int    i;
  827.     int    nAlii;
  828.     struct    protoent *ppe;
  829.  
  830.     CopyProtoEnt(ppt);
  831.  
  832.     ppe = (struct protoent *) pchData;
  833.     memcpy(ppe, &ppt->pe, sizeof(ppt->pe));
  834.     pchData += sizeof(*ppe);
  835.  
  836.     for (nAlii = 0; ppe->p_aliases[nAlii]; nAlii++);
  837.     memcpy(pchData, ppe->p_aliases, sizeof(char *) * (nAlii + 1));
  838.     ppe->p_aliases = (char **) pchData;
  839.     pchData += sizeof(char *) * (nAlii + 1);
  840.  
  841.     strcpy(pchData, ppe->p_name);
  842.     ppe->p_name = pchData;
  843.     pchData += strlen(pchData) + 1;
  844.  
  845.     for (i = 0; i < nAlii; i++)
  846.     {
  847.         strcpy(pchData, ppe->p_aliases[i]);
  848.         ppe->p_aliases[i] = pchData;
  849.         pchData += strlen(pchData) + 1;
  850.     }
  851.     return (pchData - (char *) ppe);
  852. }
  853.  
  854. SOCKET pascal far _export
  855. accept(SOCKET s, struct sockaddr FAR *addr,
  856.                           int FAR *addrlen)
  857. {
  858.     struct per_task *ppt;
  859.     struct per_socket *pps, *ppsNew;
  860.     struct data *pd;
  861.  
  862.     if ((ppt = GetTaskInfo()) == 0)
  863.         return (INVALID_SOCKET);
  864.     if ((pps = GetSocketInfo(s)) == 0)
  865.         return (INVALID_SOCKET);
  866.     if (!(pps->iFlags & PSF_ACCEPT))
  867.     {
  868.         iErrno = WSAEINVAL;
  869.         return (INVALID_SOCKET);
  870.     }
  871.     if (!pps->pdIn && (pps->iFlags & PSF_NONBLOCK))
  872.     {
  873.         FlushMessages(ppt); /* Some apps will call this in a tight loop */
  874.         iErrno = WSAEWOULDBLOCK;
  875.         return (INVALID_SOCKET);
  876.     }
  877.     if (!StartBlocking(ppt))
  878.         return (INVALID_SOCKET);
  879.     while (!pps->pdIn)
  880.     {
  881.         FlushMessages(ppt);
  882.         if (ppt->bCancel)
  883.         {
  884.             iErrno = WSAEINTR;
  885.             EndBlocking(ppt);
  886.             return (INVALID_SOCKET);
  887.         }
  888.     }
  889.  
  890.     pd = pps->pdIn;
  891.     if (addr && addrlen)
  892.     {
  893.         memcpy(addr, &pd->sin, sizeof(pd->sin));
  894.         *addrlen = sizeof(pd->sin);
  895.     }
  896.     ppsNew = (struct per_socket *) pd->pchData;
  897.  
  898.     pps->pdIn = pd->pdNext;
  899.     free(pd);
  900.     if (pps->pdIn)
  901.         Notify(pps, FD_ACCEPT);
  902.  
  903.     EndBlocking(ppt);
  904.     return ppsNew->s;
  905. }
  906.  
  907. int pascal far _export
  908. bind(SOCKET s, const struct sockaddr FAR *addr, int namelen)
  909. {
  910.     struct per_task *ppt;
  911.     int    nReturn;
  912.     struct    func_arg pfaArgs[3];
  913.     struct    func_arg pfaReturn;
  914.     struct    transmit_function tf;
  915.     struct    sockaddr    *psa;
  916.  
  917.     if ((ppt = GetTaskInfo()) == 0)
  918.         return -1;
  919.     if (!GetSocketInfo(s))
  920.         return -1;
  921.     if ((namelen < sizeof(*psa)) || IsBadReadPtr(addr, sizeof(*psa)))
  922.     {
  923.         iErrno = WSAEFAULT;
  924.         return (SOCKET_ERROR);
  925.     }
  926.     namelen = sizeof(*psa);
  927.     psa = (struct sockaddr *) malloc(namelen);
  928.     if (psa == 0)
  929.     {
  930.         iErrno = WSAENOBUFS;
  931.         return (SOCKET_ERROR);
  932.     }
  933.     memcpy(psa, addr, namelen);
  934.     psa->sa_family = htons(psa->sa_family);
  935.     INIT_ARGS(pfaArgs[0],    AT_Int,        &s,        sizeof(s)        );
  936.     INIT_CARGS(pfaArgs[1],    AT_GenPtr,    psa,        namelen            );
  937.     INIT_ARGS(pfaArgs[2],    AT_IntPtr,    &namelen,    sizeof(namelen)        );
  938.     INIT_ARGS(pfaReturn,    AT_Int,        &nReturn,    sizeof(nReturn)        );
  939.     INIT_TF(tf, FN_Bind, 3, pfaArgs, pfaReturn);
  940.     TransmitFunctionAndBlock(ppt, &tf);
  941.     free(psa);
  942.     return nReturn;
  943. }
  944.  
  945. int pascal far _export
  946. closesocket(SOCKET s)
  947. {
  948.     struct per_task *ppt;
  949.     struct per_socket *pps;
  950.     int    nReturn;
  951.     struct    func_arg pfaArgs[1];
  952.     struct    func_arg pfaReturn;
  953.     struct    transmit_function tf;
  954.  
  955.     if ((ppt = GetTaskInfo()) == 0)
  956.         return -1;
  957.     if ((pps = GetSocketInfo(s)) == 0)
  958.         return -1;
  959.     INIT_ARGS(pfaArgs[0],    AT_Int,        &s,        sizeof(s)        );
  960.     INIT_ARGS(pfaReturn,    AT_Int,        &nReturn,    sizeof(nReturn)        );
  961.     INIT_TF(tf, FN_Close, 1, pfaArgs, pfaReturn);
  962.     TransmitFunctionAndBlock(ppt, &tf);
  963.     RemoveSocket(pps); /* Assume success. Is this valid? */
  964.     return nReturn;
  965. }
  966.  
  967. int pascal far _export
  968. connect(SOCKET s, const struct sockaddr FAR *name, int namelen)
  969. {
  970.     struct per_task *ppt;
  971.     struct per_socket *pps;
  972.     int    nReturn;
  973.     struct    func_arg pfaArgs[3];
  974.     struct    func_arg pfaReturn;
  975.     struct    transmit_function tf;
  976.     struct    sockaddr    *psa;
  977.  
  978.     if ((ppt = GetTaskInfo()) == 0)
  979.         return -1;
  980.     if ((pps = GetSocketInfo(s)) == 0)
  981.         return -1;
  982.     if ((namelen < sizeof(*psa)) || IsBadReadPtr(name, sizeof(*psa)))
  983.     {
  984.         iErrno = WSAEFAULT;
  985.         return (SOCKET_ERROR);
  986.     }
  987.     namelen = sizeof(*psa);
  988.     psa = (struct sockaddr *) malloc(namelen);
  989.     if (psa == 0)
  990.     {
  991.         iErrno = WSAENOBUFS;
  992.         return (SOCKET_ERROR);
  993.     }
  994.     memcpy(psa, name, namelen);
  995.     psa->sa_family = htons(psa->sa_family);
  996.     INIT_ARGS(pfaArgs[0],    AT_Int,        &s,        sizeof(s)        );
  997.     INIT_CARGS(pfaArgs[1],    AT_GenPtr,    psa,        namelen            );
  998.     INIT_ARGS(pfaArgs[2],    AT_IntPtr,    &namelen,    sizeof(namelen)        );
  999.     INIT_ARGS(pfaReturn,    AT_Int,        &nReturn,    sizeof(nReturn)        );
  1000.     INIT_TF(tf, FN_Connect, 3, pfaArgs, pfaReturn);
  1001.     if (pps->iEvents & FD_CONNECT)
  1002.     {
  1003.         pps->iFlags |= PSF_CONNECTING;
  1004.         RemoveTXQ(TransmitFunction(&tf));
  1005.         nReturn = 0;
  1006.     }
  1007.     else
  1008.     {
  1009.         TransmitFunctionAndBlock(ppt, &tf);
  1010.         if (nReturn != -1)
  1011.             pps->iFlags |= PSF_CONNECT;
  1012.     }
  1013.     free(psa);
  1014.     return nReturn;
  1015. }
  1016.  
  1017. int pascal far _export
  1018. ioctlsocket(SOCKET s, long cmd, u_long far * arg)
  1019. {
  1020.     struct per_task *ppt;
  1021.     struct per_socket *pps;
  1022.  
  1023.     if ((ppt = GetTaskInfo()) == 0)
  1024.         return -1;
  1025.     if ((pps = GetSocketInfo(s)) == 0)
  1026.         return -1;
  1027.     switch(cmd)
  1028.     {
  1029.     case FIONBIO:
  1030.         if (IsBadReadPtr(arg, sizeof(*arg)))
  1031.         {
  1032.             iErrno = WSAEFAULT;
  1033.             return (SOCKET_ERROR);
  1034.         }
  1035.         if (*arg)
  1036.             pps->iFlags |= PSF_NONBLOCK;
  1037.         else
  1038.             pps->iFlags &= ~PSF_NONBLOCK;
  1039.         break;
  1040.  
  1041.     case FIONREAD:
  1042.         if (IsBadWritePtr(arg, sizeof(*arg)))
  1043.         {
  1044.             iErrno = WSAEFAULT;
  1045.             return (SOCKET_ERROR);
  1046.         }
  1047.         if (pps->pdIn)
  1048.             *arg = pps->pdIn->iLen - pps->pdIn->nUsed;
  1049.         else
  1050.             *arg = 0;
  1051.         break;
  1052.  
  1053.     case SIOCATMARK:
  1054.         if (IsBadWritePtr(arg, sizeof(BOOL)))
  1055.         {
  1056.             iErrno = WSAEFAULT;
  1057.             return (SOCKET_ERROR);
  1058.         }
  1059.         *(BOOL *) arg = 0;
  1060.         break;
  1061.     }
  1062.     return 0;
  1063. }
  1064.  
  1065. int pascal far _export getpeername (SOCKET s, struct sockaddr FAR *name,
  1066.                             int FAR * namelen)
  1067. {
  1068.     struct per_task *ppt;
  1069.     int    nReturn;
  1070.     struct    func_arg pfaArgs[3];
  1071.     struct    func_arg pfaReturn;
  1072.     struct    transmit_function tf;
  1073.  
  1074.     if ((ppt = GetTaskInfo()) == 0)
  1075.         return -1;
  1076.     if (!GetSocketInfo(s))
  1077.         return -1;
  1078.     INIT_ARGS(pfaArgs[0],    AT_Int,        &s,        sizeof(s)        );
  1079.     INIT_ARGS(pfaArgs[1],    AT_GenPtr,    name,        *namelen        );
  1080.     INIT_ARGS(pfaArgs[2],    AT_IntPtr,    namelen,    sizeof(*namelen)    );
  1081.     INIT_ARGS(pfaReturn,    AT_Int,        &nReturn,    sizeof(nReturn)        );
  1082.     INIT_TF(tf, FN_GetPeerName, 3, pfaArgs, pfaReturn);
  1083.     TransmitFunctionAndBlock(ppt, &tf);
  1084.     if (nReturn != -1)
  1085.         name->sa_family = ntohs(name->sa_family);
  1086.     return nReturn;
  1087. }
  1088.  
  1089. int pascal far _export getsockname (SOCKET s, struct sockaddr FAR *name,
  1090.                             int FAR * namelen)
  1091. {
  1092.     struct per_task *ppt;
  1093.     int    nReturn;
  1094.     struct    func_arg pfaArgs[3];
  1095.     struct    func_arg pfaReturn;
  1096.     struct    transmit_function tf;
  1097.  
  1098.     if ((ppt = GetTaskInfo()) == 0)
  1099.         return -1;
  1100.     if (!GetSocketInfo(s))
  1101.         return -1;
  1102.     *namelen = sizeof(struct sockaddr_in); /* Just in case */
  1103.     INIT_ARGS(pfaArgs[0],    AT_Int,        &s,        sizeof(s)        );
  1104.     INIT_ARGS(pfaArgs[1],    AT_GenPtr,    name,        *namelen        );
  1105.     INIT_ARGS(pfaArgs[2],    AT_IntPtr,    namelen,    sizeof(*namelen)    );
  1106.     INIT_ARGS(pfaReturn,    AT_Int,        &nReturn,    sizeof(nReturn)        );
  1107.     INIT_TF(tf, FN_GetSockName, 3, pfaArgs, pfaReturn);
  1108.     TransmitFunctionAndBlock(ppt, &tf);
  1109.     if (nReturn != -1)
  1110.         name->sa_family = ntohs(name->sa_family);
  1111.     return nReturn;
  1112. }
  1113.  
  1114. int pascal far _export getsockopt (SOCKET s, int level, int optname,
  1115.                            char FAR * optval, int FAR *optlen)
  1116. {
  1117.     struct per_task *ppt;
  1118.     int    nReturn;
  1119.     struct    func_arg pfaArgs[5];
  1120.     struct    func_arg pfaReturn;
  1121.     struct    transmit_function tf;
  1122.     long    iOptVal;
  1123.     short    iOptLen;
  1124.  
  1125.     iOptLen = sizeof(long);
  1126.  
  1127.     if ((ppt = GetTaskInfo()) == 0)
  1128.         return -1;
  1129.     if (!GetSocketInfo(s))
  1130.         return -1;
  1131.     if (level != IPPROTO_TCP && level != (int) SOL_SOCKET)
  1132.     {
  1133.         iErrno = WSAEINVAL;
  1134.         return (SOCKET_ERROR);
  1135.     }
  1136.     INIT_ARGS(pfaArgs[0],    AT_Int,        &s,        sizeof(s)        );
  1137.     INIT_ARGS(pfaArgs[1],    AT_Int,        &level,        sizeof(level)        );
  1138.     INIT_ARGS(pfaArgs[2],    AT_Int,        &optname,    sizeof(optname)        );
  1139.     if (optname == SO_LINGER)
  1140.         INIT_ARGS(pfaArgs[3],    AT_GenPtr,    optval,        iOptLen        );
  1141.     else
  1142.         INIT_ARGS(pfaArgs[3],    AT_Int32Ptr,    &iOptVal,    iOptLen        );
  1143.     INIT_ARGS(pfaArgs[4],    AT_IntPtr,    &iOptLen,    sizeof(iOptLen)        );
  1144.     INIT_ARGS(pfaReturn,    AT_Int,        &nReturn,    sizeof(nReturn)        );
  1145.     INIT_TF(tf, FN_GetSockOpt, 5, pfaArgs, pfaReturn);
  1146.     if (TransmitFunctionAndBlock(ppt, &tf))
  1147.     {
  1148.         if (optname == SO_LINGER)
  1149.         {
  1150.             *optlen = sizeof(struct linger);
  1151.         }
  1152.         else
  1153.         {
  1154.             *optlen = sizeof(int);
  1155.             * (int FAR *) optval = (int) iOptVal;
  1156.         }
  1157.     }
  1158.     return nReturn;
  1159. }
  1160.  
  1161. u_long pascal far _export htonl (u_long hostlong)
  1162. {
  1163.     char    *pchValue = (char *) &hostlong;
  1164.     char    c;
  1165.  
  1166.     c = pchValue[0];
  1167.     pchValue[0] = pchValue[3];
  1168.     pchValue[3] = c;
  1169.     c = pchValue[1];
  1170.     pchValue[1] = pchValue[2];
  1171.     pchValue[2] = c;
  1172.     return hostlong;
  1173. }
  1174.  
  1175. u_short pascal far _export htons (u_short hostshort)
  1176. {
  1177.     char    *pchValue = (char *) &hostshort;
  1178.     char    c;
  1179.  
  1180.     c = pchValue[0];
  1181.     pchValue[0] = pchValue[1];
  1182.     pchValue[1] = c;
  1183.     return hostshort;
  1184. }
  1185.  
  1186. unsigned long pascal far _export inet_addr (const char FAR * cp)
  1187. {
  1188.     unsigned long    iValue;
  1189.     char    *pchValue = (char *) &iValue;
  1190.  
  1191.     if (!GetTaskInfo())
  1192.         return (INADDR_NONE);
  1193.     pchValue[0] = atoi(cp);
  1194.     cp = strchr(cp, '.');
  1195.     if (cp)
  1196.     {
  1197.         cp++;
  1198.         pchValue[1] = atoi(cp);
  1199.         cp = strchr(cp, '.');
  1200.         if (cp)
  1201.         {
  1202.             cp++;
  1203.             pchValue[2] = atoi(cp);
  1204.             cp = strchr(cp, '.');
  1205.             if (cp)
  1206.             {
  1207.                 cp++;
  1208.                 pchValue[3] = atoi(cp);
  1209.                 cp = strchr(cp, '.');
  1210.                 if (!cp)
  1211.                 {
  1212.                     return iValue;
  1213.                 }
  1214.             }
  1215.         }
  1216.     }
  1217.     return (INADDR_NONE);
  1218. }
  1219.  
  1220. char FAR * pascal far _export inet_ntoa (struct in_addr in)
  1221. {
  1222.     struct per_task *ppt;
  1223.  
  1224.     if ((ppt = GetTaskInfo()) == 0)
  1225.         return 0;
  1226.  
  1227.     sprintf(ppt->achAddress, "%d.%d.%d.%d",
  1228.             (int) in.S_un.S_un_b.s_b1,
  1229.             (int) in.S_un.S_un_b.s_b2,
  1230.             (int) in.S_un.S_un_b.s_b3,
  1231.             (int) in.S_un.S_un_b.s_b4);
  1232.     return ppt->achAddress;
  1233. }
  1234.  
  1235. int pascal far _export listen (SOCKET s, int backlog)
  1236. {
  1237.     struct per_task *ppt;
  1238.     struct per_socket *pps;
  1239.     int    nReturn;
  1240.     struct    func_arg pfaArgs[2];
  1241.     struct    func_arg pfaReturn;
  1242.     struct    transmit_function tf;
  1243.  
  1244.     if ((ppt = GetTaskInfo()) == 0)
  1245.         return -1;
  1246.     if ((pps = GetSocketInfo(s)) == 0)
  1247.         return -1;
  1248.     if (pps->iFlags & PSF_CONNECT)
  1249.     {
  1250.         iErrno = WSAEISCONN;
  1251.         return -1;
  1252.     }
  1253.     INIT_ARGS(pfaArgs[0],    AT_Int,        &s,        sizeof(s)        );
  1254.     INIT_ARGS(pfaArgs[1],    AT_Int,        &backlog,    sizeof(backlog)        );
  1255.     INIT_ARGS(pfaReturn,    AT_Int,        &nReturn,    sizeof(nReturn)        );
  1256.     INIT_TF(tf, FN_Listen, 2, pfaArgs, pfaReturn);
  1257.     TransmitFunctionAndBlock(ppt, &tf);
  1258.     if (nReturn != -1)
  1259.         pps->iFlags |= PSF_ACCEPT;
  1260.     return nReturn;
  1261. }
  1262.  
  1263. u_long pascal far _export ntohl (u_long netlong)
  1264. {
  1265.     char    *pchValue = (char *) &netlong;
  1266.     char    c;
  1267.  
  1268.     c = pchValue[0];
  1269.     pchValue[0] = pchValue[3];
  1270.     pchValue[3] = c;
  1271.     c = pchValue[1];
  1272.     pchValue[1] = pchValue[2];
  1273.     pchValue[2] = c;
  1274.     return netlong;
  1275. }
  1276.  
  1277. u_short pascal far _export ntohs (u_short netshort)
  1278. {
  1279.     char    *pchValue = (char *) &netshort;
  1280.     char    c;
  1281.  
  1282.     c = pchValue[0];
  1283.     pchValue[0] = pchValue[1];
  1284.     pchValue[1] = c;
  1285.     return netshort;
  1286. }
  1287.  
  1288. int pascal far _export recv (SOCKET s, char FAR * buf, int len, int flags)
  1289. {
  1290.     return recvfrom(s, buf, len, flags, 0, 0);
  1291. }
  1292.  
  1293. int pascal far _export recvfrom (SOCKET s, char FAR * buf, int len, int flags,
  1294.                          struct sockaddr FAR *from, int FAR * fromlen)
  1295. {
  1296.     struct per_task *ppt;
  1297.     struct per_socket *pps;
  1298.     struct data *pd;
  1299.  
  1300.     if ((ppt = GetTaskInfo()) == 0)
  1301.         return -1;
  1302.     if ((pps = GetSocketInfo(s)) == 0)
  1303.         return -1;
  1304.     if (pps->iFlags & PSF_CLOSED)
  1305.     {
  1306.         /* Haven't you got the message yet? */
  1307.         iErrno = WSAENOTCONN;
  1308.         return -1;
  1309.     }
  1310.     if (pps->iFlags & PSF_ACCEPT)
  1311.     {
  1312.         iErrno = WSAENOTCONN;
  1313.         return -1;
  1314.     }
  1315.     if (pps->iFlags & PSF_SHUTDOWN)
  1316.     {
  1317.         iErrno = WSAESHUTDOWN;
  1318.         return -1;
  1319.     }
  1320.     if (!pps->pdIn && (pps->iFlags & PSF_NONBLOCK))
  1321.     {
  1322.         FlushMessages(ppt); /* Some apps will call this in a tight loop */
  1323.         iErrno = WSAEWOULDBLOCK;
  1324.         return -1;
  1325.     }
  1326.     /*
  1327.      * Validate the user buffer
  1328.      */
  1329.     if (IsBadWritePtr(buf, len)) /* Make sure we can write the user data buffer */
  1330.     {
  1331.         iErrno = WSAEFAULT;
  1332.         return (SOCKET_ERROR);
  1333.     }
  1334.     /*
  1335.      * If we have a 'from' buffer, make sure that
  1336.      * we can read and write it. Also make sure that
  1337.      * the buffer passed is large enough to hold a sockaddr.
  1338.      */
  1339.     if (from)
  1340.     {
  1341.         if (!fromlen ||                /* Did the user specify a length */
  1342.             IsBadReadPtr(fromlen, sizeof(*fromlen)) || /* Can we read length ?? */
  1343.             IsBadWritePtr(fromlen, sizeof(*fromlen)) || /* Can we write it ??    */
  1344.             (*fromlen < sizeof(struct sockaddr)) ) /* Can it hold a sockaddr? */
  1345.         {
  1346.             iErrno = WSAEFAULT;
  1347.             return (SOCKET_ERROR);
  1348.         }
  1349.     }
  1350.     if (!StartBlocking(ppt))
  1351.         return -1;
  1352.     while (!pps->pdIn)
  1353.     {
  1354.         FlushMessages(ppt);
  1355.         if (ppt->bCancel)
  1356.         {
  1357.             iErrno = WSAEINTR;
  1358.             EndBlocking(ppt);
  1359.             return -1;
  1360.         }
  1361.     }
  1362.  
  1363.     pd = pps->pdIn;
  1364.     if (from)
  1365.     {
  1366.         memcpy(from, &pd->sin, sizeof(pd->sin));
  1367.         *fromlen = sizeof(pd->sin);
  1368.     }
  1369.     if (len > pd->iLen - pd->nUsed)
  1370.         len = pd->iLen - pd->nUsed;
  1371.     memcpy(buf, pd->pchData + pd->nUsed, len);
  1372.     pd->nUsed += len;
  1373.     if (pd->nUsed == pd->iLen)
  1374.     {
  1375.         pps->pdIn = pd->pdNext;
  1376.         free(pd->pchData);
  1377.         free(pd);
  1378.         if (pps->pdIn)
  1379.             Notify(pps, pps->pdIn->iLen ? FD_READ : FD_CLOSE);
  1380.     }
  1381.     else
  1382.     {
  1383.         Notify(pps, FD_READ);
  1384.     }
  1385.  
  1386.     EndBlocking(ppt);
  1387.     return len;
  1388. }
  1389.  
  1390. #define    PPS_ERROR    ((struct per_socket **) -1)
  1391.  
  1392. static    struct    per_socket **
  1393. GetPPS(fd_set *fds)
  1394. {
  1395.     struct per_socket **pps;
  1396.     u_short    i;
  1397.  
  1398.     if (!fds || !fds->fd_count)
  1399.         return 0;
  1400.     pps = (struct per_socket **) malloc(sizeof(struct per_socket *) *
  1401.                         fds->fd_count);
  1402.     if (pps == 0)
  1403.         return (pps);
  1404.     for (i = 0; i < fds->fd_count; i++)
  1405.     {
  1406.         pps[i] = GetSocketInfo(fds->fd_array[i]);
  1407.         if (!pps[i])
  1408.         {
  1409.             free(pps);
  1410.             return PPS_ERROR;
  1411.         }
  1412.     }
  1413.     return pps;
  1414. }
  1415.  
  1416.  
  1417. int pascal far _export select (int nfds, fd_set *readfds, fd_set far *writefds,
  1418.                 fd_set *exceptfds, const struct timeval far *timeout)
  1419. {
  1420.     struct per_task *ppt;
  1421.     struct per_socket **ppsRead, **ppsWrite, **ppsExcept;
  1422.     BOOL    bOneOK = FALSE;
  1423.     BOOL    bTimedOut = FALSE;
  1424.     unsigned    long    tExpire;
  1425.     u_short i;
  1426.     u_short    iOld, iNew;
  1427.  
  1428.     if (timeout)
  1429.     {
  1430.         tExpire = GetTickCount();
  1431.         tExpire += timeout->tv_usec / 1000 + timeout->tv_sec * 1000;
  1432.     }
  1433.     if ((ppt = GetTaskInfo()) == 0)
  1434.         return -1;
  1435.     if (!StartBlocking(ppt))
  1436.         return -1;
  1437.  
  1438.     ppsRead = GetPPS(readfds);
  1439.     if (ppsRead == PPS_ERROR)
  1440.         return -1;
  1441.     ppsWrite = GetPPS(writefds);
  1442.     if (ppsWrite == PPS_ERROR)
  1443.     {
  1444.         free(ppsRead);
  1445.         return -1;
  1446.     }
  1447.     ppsExcept = GetPPS(exceptfds);
  1448.     if (ppsExcept == PPS_ERROR)
  1449.     {
  1450.         free(ppsRead);
  1451.         free(ppsWrite);
  1452.         return -1;
  1453.     }
  1454.         
  1455.     while (!bOneOK && !bTimedOut && !ppt->bCancel)
  1456.     {
  1457.         FlushMessages(ppt);
  1458.         if (ppsWrite)
  1459.         {
  1460.             for (i = 0; i < writefds->fd_count; i++)
  1461.             {
  1462.                 if (((!ppsWrite[i]->iFlags & PSF_CONNECTING) ||
  1463.                      (ppsWrite[i]->iFlags & PSF_CONNECT)) &&
  1464.                     ppsWrite[i]->nOutstanding < MAX_OUTSTANDING)
  1465.                     bOneOK = TRUE;
  1466.             }
  1467.         }
  1468.         if (ppsRead)
  1469.         {
  1470.             for (i = 0; i < readfds->fd_count; i++)
  1471.             {
  1472.                 if (ppsRead[i]->pdIn)
  1473.                     bOneOK = TRUE;
  1474.             }
  1475.         }
  1476.         if (timeout && GetTickCount() >= tExpire)
  1477.             bTimedOut = TRUE;
  1478.     }
  1479.  
  1480.     nfds = 0;
  1481.     if (readfds)
  1482.     {
  1483.         for (iOld = iNew = 0; iOld < readfds->fd_count; iOld++)
  1484.         {
  1485.             if (iOld != iNew)
  1486.                 readfds->fd_array[iNew] =
  1487.                         readfds->fd_array[iOld];
  1488.             if (ppsRead[iOld]->pdIn)
  1489.                 iNew++;
  1490.         }
  1491.         readfds->fd_count = iNew;
  1492.         nfds += iNew;
  1493.     }
  1494.     if (writefds)
  1495.     {
  1496.         for (iOld = iNew = 0; iOld < writefds->fd_count; iOld++)
  1497.         {
  1498.             if (iOld != iNew)
  1499.                 writefds->fd_array[iNew] =
  1500.                         writefds->fd_array[iOld];
  1501.             if (((!ppsWrite[iOld]->iFlags & PSF_CONNECTING) ||
  1502.                      (ppsWrite[iOld]->iFlags & PSF_CONNECT)) &&
  1503.                     ppsWrite[iOld]->nOutstanding < MAX_OUTSTANDING)
  1504.                 iNew++;
  1505.         }
  1506.         writefds->fd_count = iNew;
  1507.         nfds += iNew;
  1508.     }
  1509.     if (exceptfds)
  1510.         exceptfds->fd_count = 0;
  1511.  
  1512.     EndBlocking(ppt);
  1513.     if (ppsRead)
  1514.         free(ppsRead);
  1515.     if (ppsWrite)
  1516.         free(ppsWrite);
  1517.     if (ppsExcept)
  1518.         free(ppsExcept);
  1519.     if (ppt->bCancel && !nfds)
  1520.     {
  1521.         iErrno = WSAEINTR;
  1522.         return -1;
  1523.     }
  1524.     else
  1525.     {
  1526.         return nfds;
  1527.     }
  1528. }
  1529.  
  1530. /* We don't wait for the result of a send because some telnets don't behave
  1531.  * correctly with WSAEINPROGRESS when sending. This results in characters
  1532.  * being dropped to hell while we wait for the response from the host.
  1533.  * We return success unless the socket is not connected or is closed.
  1534.  * This is fairly safe on connected sockets (which is what uses send).
  1535.  *
  1536.  * We don't do this with sendto because it's really only telnets that suffer
  1537.  * from this, although that doesn't stop another application from having the
  1538.  * same problem with sendto later on.
  1539.  *
  1540.  * This causes certain FTP clients to display phenomenal transfer rates.
  1541.  * They should be checking the transfer rates *after* closing their sockets.
  1542.  */
  1543. int pascal far _export send (SOCKET s, const char FAR * buf, int len, int flags)
  1544. {
  1545.     struct per_task *ppt;
  1546.     struct per_socket *pps;
  1547.     int    nReturn;
  1548.     struct    func_arg pfaArgs[4];
  1549.     struct    func_arg pfaReturn;
  1550.     struct    transmit_function tf;
  1551.  
  1552.     if ((ppt = GetTaskInfo()) == 0)
  1553.         return -1;
  1554.     if ((pps = GetSocketInfo(s)) == 0)
  1555.         return -1;
  1556.     if ((pps->iFlags & PSF_CONNECTING) &&
  1557.         !(pps->iFlags & PSF_CONNECT))
  1558.     {
  1559.         FlushMessages(ppt); /* Some apps will call this in a tight loop */
  1560.         iErrno = WSAEWOULDBLOCK;
  1561.         return -1;
  1562.     }
  1563.     if (!(pps->iFlags & PSF_CONNECT))
  1564.     {
  1565.         iErrno = WSAENOTCONN;
  1566.         return -1;
  1567.     }
  1568.     if (pps->iFlags & PSF_CLOSED)
  1569.     {
  1570.         iErrno = WSAECONNRESET;
  1571.         return -1;
  1572.     }
  1573.     if (IsBadReadPtr(buf, len))    /* Is the data buffer readable ? */
  1574.     {
  1575.         iErrno = WSAEFAULT;
  1576.         return (SOCKET_ERROR);
  1577.     }
  1578.     if (pps->nOutstanding >= MAX_OUTSTANDING)
  1579.     {
  1580.         if (pps->iFlags & PSF_NONBLOCK)
  1581.         {
  1582.             FlushMessages(ppt); /* Some apps will call this in a tight loop */
  1583.             iErrno = WSAEWOULDBLOCK;
  1584.             return -1;
  1585.         }
  1586.         if (!StartBlocking(ppt))
  1587.         {
  1588.             iErrno = WSAEINPROGRESS;
  1589.             return -1;
  1590.         }
  1591.         while (pps->nOutstanding >= MAX_OUTSTANDING && !ppt->bCancel)
  1592.             FlushMessages(ppt);
  1593.         EndBlocking(ppt);
  1594.         if (ppt->bCancel)
  1595.         {
  1596.             ppt->bCancel = FALSE;
  1597.             iErrno = WSAEINTR;
  1598.             return -1;
  1599.         }
  1600.     }
  1601.     INIT_ARGS(pfaArgs[0],    AT_Int,        &s,        sizeof(s)        );
  1602.     INIT_CARGS(pfaArgs[1],    AT_GenPtr,    buf,        len            );
  1603.     INIT_ARGS(pfaArgs[2],    AT_IntPtr,    &len,        sizeof(len)        );
  1604.     INIT_ARGS(pfaArgs[3],    AT_Int,        &flags,        sizeof(flags)        );
  1605.     INIT_ARGS(pfaReturn,    AT_Int,        &nReturn,    sizeof(nReturn)        );
  1606.     INIT_TF(tf, FN_Send, 4, pfaArgs, pfaReturn);
  1607.     RemoveTXQ(TransmitFunction(&tf));
  1608.     pps->nOutstanding += len;
  1609.     if (pps->nOutstanding < MAX_OUTSTANDING)
  1610.         Notify(pps, FD_WRITE);
  1611.     return len;
  1612. }
  1613.  
  1614. int pascal far _export sendto (SOCKET s, const char FAR * buf, int len, int flags,
  1615.                        const struct sockaddr FAR *to, int tolen)
  1616. {
  1617.     struct per_task *ppt;
  1618.     struct per_socket *pps;
  1619.     int    nReturn;
  1620.     struct    func_arg pfaArgs[6];
  1621.     struct    func_arg pfaReturn;
  1622.     struct    transmit_function tf;
  1623.     struct    sockaddr    *psa;
  1624.  
  1625.     if ((ppt = GetTaskInfo()) == 0)
  1626.         return -1;
  1627.     if ((pps = GetSocketInfo(s)) == 0)
  1628.         return -1;
  1629.     if (pps->nOutstanding >= MAX_OUTSTANDING)
  1630.     {
  1631.         if (pps->iFlags & PSF_NONBLOCK)
  1632.         {
  1633.             FlushMessages(ppt); /* Some apps will call this in a tight loop */
  1634.             iErrno = WSAEWOULDBLOCK;
  1635.             return -1;
  1636.         }
  1637.         if (!StartBlocking(ppt))
  1638.         {
  1639.             iErrno = WSAEINPROGRESS;
  1640.             return -1;
  1641.         }
  1642.         while (pps->nOutstanding >= MAX_OUTSTANDING && !ppt->bCancel)
  1643.             FlushMessages(ppt);
  1644.         EndBlocking(ppt);
  1645.         if (ppt->bCancel)
  1646.         {
  1647.             ppt->bCancel = FALSE;
  1648.             iErrno = WSAEINTR;
  1649.             return -1;
  1650.         }
  1651.     }
  1652.     psa = (struct sockaddr *) malloc(tolen);
  1653.     if (psa == 0)
  1654.     {
  1655.         iErrno = WSAENOBUFS;
  1656.         return (SOCKET_ERROR);
  1657.     }
  1658.     /*
  1659.      * Sanity check the arguments.
  1660.      */
  1661.     if ((tolen < sizeof(*psa)) ||
  1662.         IsBadReadPtr(buf, len) ||
  1663.         IsBadReadPtr(to, sizeof(*psa)) )
  1664.     {
  1665.         free(psa);
  1666.         iErrno = WSAEFAULT;
  1667.         return (SOCKET_ERROR);
  1668.     }
  1669.     /*
  1670.      * The WINSOCK spec allows namelen's that are larger
  1671.      * then the size of a sockaddr. The WSAT expects sendto()s
  1672.      * with tolen's > sizeof(struct sockaddr) to succeed.
  1673.      * Make sure that this condition will not cause the
  1674.      * other side to fail (we don't know if the other side
  1675.      * will fail or not with tolen's > sizeof(struct sockaddr).
  1676.      */
  1677.     tolen = sizeof(*psa);
  1678.  
  1679.     memcpy(psa, to, tolen);
  1680.     psa->sa_family = htons(psa->sa_family);
  1681.     INIT_ARGS(pfaArgs[0],    AT_Int,        &s,        sizeof(s)        );
  1682.     INIT_CARGS(pfaArgs[1],    AT_GenPtr,    buf,        len            );
  1683.     INIT_ARGS(pfaArgs[2],    AT_IntPtr,    &len,        sizeof(len)        );
  1684.     INIT_ARGS(pfaArgs[3],    AT_Int,        &flags,        sizeof(flags)        );
  1685.     INIT_CARGS(pfaArgs[4],    AT_GenPtr,    psa,        tolen            );
  1686.     INIT_ARGS(pfaArgs[5],    AT_Int,        &tolen,        sizeof(tolen)        );
  1687.     INIT_ARGS(pfaReturn,    AT_Int,        &nReturn,    sizeof(nReturn)        );
  1688.  
  1689.     INIT_TF(tf, FN_SendTo, 6, pfaArgs, pfaReturn);
  1690.     RemoveTXQ(TransmitFunction(&tf));
  1691.     pps->nOutstanding += len;
  1692.     if (pps->nOutstanding < MAX_OUTSTANDING)
  1693.         Notify(pps, FD_WRITE);
  1694.     free(psa);
  1695.     Notify(pps, FD_WRITE);
  1696.     return len;
  1697. }
  1698.  
  1699. int pascal far _export setsockopt (SOCKET s, int level, int optname,
  1700.                            const char FAR * optval, int optlen)
  1701. {
  1702.     struct per_task *ppt;
  1703.     int    nReturn;
  1704.     struct    func_arg pfaArgs[5];
  1705.     struct    func_arg pfaReturn;
  1706.     struct    transmit_function tf;
  1707.     long    iOptVal;
  1708.     short    iOptLen;
  1709.  
  1710.     iOptLen = sizeof(long);
  1711.  
  1712.     if ((ppt = GetTaskInfo()) == 0)
  1713.         return -1;
  1714.     if (!GetSocketInfo(s))
  1715.         return -1;
  1716.     /*
  1717.      * Sanity check the arguments.
  1718.      */
  1719.     if (IsBadReadPtr(optval, optlen))    /* Is the option value readable? */
  1720.     {
  1721.         iErrno = WSAEFAULT;
  1722.         return (SOCKET_ERROR);
  1723.     }
  1724.     INIT_ARGS(pfaArgs[0],    AT_Int,        &s,        sizeof(s)        );
  1725.     INIT_ARGS(pfaArgs[1],    AT_Int,        &level,        sizeof(level)        );
  1726.     INIT_ARGS(pfaArgs[2],    AT_Int,        &optname,    sizeof(optname)        );
  1727.     if (optname == SO_LINGER)
  1728.     {
  1729.         INIT_ARGS(pfaArgs[3],    AT_GenPtr,    optval,        iOptLen        );
  1730.     }
  1731.     else
  1732.     {
  1733.         iOptVal = *optval;
  1734.         INIT_ARGS(pfaArgs[3],    AT_Int32Ptr,    &iOptVal,    iOptLen        );
  1735.     }
  1736.     INIT_ARGS(pfaArgs[4],    AT_Int,        &iOptLen,    sizeof(iOptLen)        );
  1737.     INIT_ARGS(pfaReturn,    AT_Int,        &nReturn,    sizeof(nReturn)        );
  1738.     INIT_TF(tf, FN_SetSockOpt, 5, pfaArgs, pfaReturn);
  1739.     /* If we get this far, assume the host will grok.
  1740.      * Better to return immediately because applications
  1741.      * won't expect us to block here.
  1742.      */
  1743.     RemoveTXQ(TransmitFunction(&tf));
  1744.     return 0;
  1745. }
  1746.  
  1747. int pascal far _export shutdown (SOCKET s, int how)
  1748. {
  1749.     struct per_task *ppt;
  1750.     struct per_socket *pps;
  1751.     int    nReturn;
  1752.     struct    func_arg pfaArgs[2];
  1753.     struct    func_arg pfaReturn;
  1754.     struct    transmit_function tf;
  1755.  
  1756.     if ((ppt = GetTaskInfo()) == 0)
  1757.         return -1;
  1758.     if ((pps = GetSocketInfo(s)) == 0)
  1759.         return -1;
  1760.     INIT_ARGS(pfaArgs[0],    AT_Int,        &s,        sizeof(s)        );
  1761.     INIT_ARGS(pfaArgs[1],    AT_Int,        &how,        sizeof(how)        );
  1762.     INIT_ARGS(pfaReturn,    AT_Int,        &nReturn,    sizeof(nReturn)        );
  1763.     INIT_TF(tf, FN_Shutdown, 2, pfaArgs, pfaReturn);
  1764.     TransmitFunctionAndBlock(ppt, &tf);
  1765.     if (nReturn != -1 && (how == 0 || how == 2))
  1766.         pps->iFlags |= PSF_SHUTDOWN;
  1767.     return nReturn;
  1768. }
  1769.  
  1770. SOCKET pascal far _export socket (int af, int type, int protocol)
  1771. {
  1772.     struct per_task *ppt;
  1773.     int    nReturn;
  1774.     struct    func_arg pfaArgs[3];
  1775.     struct    func_arg pfaReturn;
  1776.     struct    transmit_function tf;
  1777.     struct    per_socket *pps;
  1778.  
  1779.     if ((ppt = GetTaskInfo()) == 0)
  1780.         return (INVALID_SOCKET);
  1781.     INIT_ARGS(pfaArgs[0],    AT_Int,        &af,        sizeof(af)        );
  1782.     INIT_ARGS(pfaArgs[1],    AT_Int,        &type,        sizeof(type)        );
  1783.     INIT_ARGS(pfaArgs[2],    AT_Int,        &protocol,    sizeof(protocol)    );
  1784.     INIT_ARGS(pfaReturn,    AT_Int,        &nReturn,    sizeof(nReturn)        );
  1785.     INIT_TF(tf, FN_Socket, 3, pfaArgs, pfaReturn);
  1786.     TransmitFunctionAndBlock(ppt, &tf);
  1787.     if (nReturn != -1)
  1788.     {
  1789.         pps = NewSocket(ppt, nReturn);
  1790.         switch(type)
  1791.         {
  1792.         case SOCK_STREAM:
  1793.         case SOCK_SEQPACKET:
  1794.             pps->iFlags |= PSF_MUSTCONN;
  1795.             break;
  1796.  
  1797.         case SOCK_DGRAM:
  1798.         case SOCK_RAW:
  1799.         case SOCK_RDM:
  1800.             pps->iFlags &= ~PSF_MUSTCONN;
  1801.             break;
  1802.         }
  1803.     }
  1804.     return nReturn;
  1805. }
  1806.  
  1807. struct hostent FAR * pascal far _export gethostbyaddr(const char FAR * addr,
  1808.                                               int len, int type)
  1809. {
  1810.     struct per_task *ppt;
  1811.     struct    func_arg pfaArgs[3];
  1812.     struct    func_arg pfaReturn;
  1813.     struct    transmit_function tf;
  1814.  
  1815.     if ((ppt = GetTaskInfo()) == 0)
  1816.         return 0;
  1817.     /*
  1818.      * Sanity check the arguments. For the first two conditions
  1819.      * of this check, the WINSOCK spec does not specify the correct
  1820.      * iErrno value to return if they fail. Here we use EFAULT
  1821.      * for everything.
  1822.      */
  1823.     if ((type != PF_INET) ||            /* WINSOCK spec says this must be PF_INET */
  1824.         (len != 4) ||                /* WINSOCK spec says must be 4 for PF_INET */
  1825.         IsBadReadPtr(addr, len))            /* Can we read the host address */
  1826.     {
  1827.         iErrno = WSAEFAULT;
  1828.         return 0;
  1829.     }
  1830.     INIT_CARGS(pfaArgs[0],    AT_GenPtr,    addr,        len            );
  1831.     INIT_ARGS(pfaArgs[1],    AT_Int,        &len,        sizeof(len)        );
  1832.     INIT_ARGS(pfaArgs[2],    AT_Int,        &type,        sizeof(type)        );
  1833.     INIT_ARGS(pfaReturn,    AT_GenPtr,    ppt->achHostEnt,MAX_HOST_ENT        );
  1834.     INIT_TF(tf, FN_HostByAddr, 3, pfaArgs, pfaReturn);
  1835.     if (TransmitFunctionAndBlock(ppt, &tf))
  1836.     {
  1837.         CopyHostEnt(ppt);
  1838.         return &ppt->he;
  1839.     }
  1840.     else
  1841.     {
  1842.         return 0;
  1843.     }
  1844. }
  1845.  
  1846. struct hostent FAR * pascal far _export gethostbyname(const char FAR * name)
  1847. {
  1848.     struct per_task *ppt;
  1849.     struct    func_arg pfaArgs[1];
  1850.     struct    func_arg pfaReturn;
  1851.     struct    transmit_function tf;
  1852.  
  1853.     if ((ppt = GetTaskInfo()) == 0)
  1854.         return 0;
  1855.     /*
  1856.      * Sanity check the argument.
  1857.      */
  1858.     if (IsBadReadPtr(name, 1))    /* Make sure we can read at least 1 byte */
  1859.     {
  1860.         iErrno = WSAEFAULT;
  1861.         return 0;
  1862.     }
  1863.     INIT_CARGS(pfaArgs[0],    AT_String,    name,        strlen(name) + 1    );
  1864.     INIT_ARGS(pfaReturn,    AT_GenPtr,    ppt->achHostEnt,MAX_HOST_ENT        );
  1865.     INIT_TF(tf, FN_HostByName, 1, pfaArgs, pfaReturn);
  1866.     if (TransmitFunctionAndBlock(ppt, &tf))
  1867.     {
  1868.         CopyHostEnt(ppt);
  1869.         return &ppt->he;
  1870.     }
  1871.     else
  1872.     {
  1873.         return 0;
  1874.     }
  1875. }
  1876.  
  1877. struct servent FAR * pascal far _export getservbyport(int port, const char FAR * proto)
  1878. {
  1879.     struct per_task *ppt;
  1880.     struct    func_arg pfaArgs[2];
  1881.     struct    func_arg pfaReturn;
  1882.     struct    transmit_function tf;
  1883.  
  1884.     if ((ppt = GetTaskInfo()) == 0)
  1885.         return 0;
  1886.     PORTSWAP(port);
  1887.     if (!proto)
  1888.         proto = "";
  1889.     /*
  1890.      * Sanity check the argumets.
  1891.      */
  1892.     else if (IsBadReadPtr(proto, 1))    /* Make sure we can read at least 1 byte */
  1893.     {
  1894.             iErrno = WSAEFAULT;
  1895.             return 0;
  1896.     }
  1897.     INIT_ARGS(pfaArgs[0],    AT_Int,        &port,        sizeof(port)        );
  1898.     INIT_CARGS(pfaArgs[1],    AT_String,    proto,        strlen(proto) + 1    );
  1899.     INIT_ARGS(pfaReturn,    AT_GenPtr,    ppt->achServEnt,MAX_HOST_ENT        );
  1900.     INIT_TF(tf, FN_ServByPort, 2, pfaArgs, pfaReturn);
  1901.     if (TransmitFunctionAndBlock(ppt, &tf))
  1902.     {
  1903.         CopyServEnt(ppt);
  1904.         return &ppt->se;
  1905.     }
  1906.     else
  1907.     {
  1908.         return 0;
  1909.     }
  1910. }
  1911.  
  1912. struct servent FAR * pascal far _export getservbyname(const char FAR * name,
  1913.                                               const char FAR * proto)
  1914. {
  1915.     struct per_task *ppt;
  1916.     struct    func_arg pfaArgs[2];
  1917.     struct    func_arg pfaReturn;
  1918.     struct    transmit_function tf;
  1919.  
  1920.     if ((ppt = GetTaskInfo()) == 0)
  1921.         return 0;
  1922.     if (!proto)
  1923.         proto = "";
  1924.     INIT_CARGS(pfaArgs[0],    AT_String,    name,        strlen(name) + 1    );
  1925.     INIT_CARGS(pfaArgs[1],    AT_String,    proto,        strlen(proto) + 1    );
  1926.     INIT_ARGS(pfaReturn,    AT_GenPtr,    ppt->achServEnt,MAX_HOST_ENT        );
  1927.     INIT_TF(tf, FN_ServByName, 2, pfaArgs, pfaReturn);
  1928.     if (TransmitFunctionAndBlock(ppt, &tf))
  1929.     {
  1930.         CopyServEnt(ppt);
  1931.         return &ppt->se;
  1932.     }
  1933.     else
  1934.     {
  1935.         return 0;
  1936.     }
  1937. }
  1938.  
  1939. struct protoent FAR * pascal far _export getprotobynumber(int proto)
  1940. {
  1941.     struct per_task *ppt;
  1942.     struct    func_arg pfaArgs[1];
  1943.     struct    func_arg pfaReturn;
  1944.     struct    transmit_function tf;
  1945.  
  1946.     if ((ppt = GetTaskInfo()) == 0)
  1947.         return 0;
  1948.     INIT_ARGS(pfaArgs[0],    AT_Int,        &proto,        sizeof(proto)    );
  1949.     INIT_ARGS(pfaReturn,    AT_GenPtr,    ppt->achProtoEnt,MAX_HOST_ENT    );
  1950.     INIT_TF(tf, FN_ProtoByNumber, 1, pfaArgs, pfaReturn);
  1951.     if (TransmitFunctionAndBlock(ppt, &tf))
  1952.     {
  1953.         CopyProtoEnt(ppt);
  1954.         return &ppt->pe;
  1955.     }
  1956.     else
  1957.     {
  1958.         return 0;
  1959.     }
  1960. }
  1961.  
  1962. struct protoent FAR * pascal far _export getprotobyname(const char FAR * name)
  1963. {
  1964.     struct per_task *ppt;
  1965.     struct    func_arg pfaArgs[1];
  1966.     struct    func_arg pfaReturn;
  1967.     struct    transmit_function tf;
  1968.  
  1969.     if ((ppt = GetTaskInfo()) == 0)
  1970.         return 0;
  1971.     INIT_CARGS(pfaArgs[0],    AT_String,    name,        strlen(name) + 1    );
  1972.     INIT_ARGS(pfaReturn,    AT_GenPtr,    ppt->achProtoEnt,MAX_HOST_ENT        );
  1973.     INIT_TF(tf, FN_ProtoByName, 1, pfaArgs, pfaReturn);
  1974.     if (TransmitFunctionAndBlock(ppt, &tf))
  1975.     {
  1976.         CopyProtoEnt(ppt);
  1977.         return &ppt->pe;
  1978.     }
  1979.     else
  1980.     {
  1981.         return 0;
  1982.     }
  1983. }
  1984.  
  1985. int pascal far _export
  1986. gethostname(char *name, int namelen)
  1987. {
  1988.     struct per_task *ppt;
  1989.     int    nReturn;
  1990.     struct    func_arg pfaArgs[2];
  1991.     struct    func_arg pfaReturn;
  1992.     struct    transmit_function tf;
  1993.  
  1994.     if ((ppt = GetTaskInfo()) == 0)
  1995.         return -1;
  1996.     INIT_ARGS(pfaArgs[0],    AT_String,    name,        namelen        );
  1997.     INIT_ARGS(pfaArgs[1],    AT_Int,        &namelen,    sizeof(namelen)    );
  1998.     INIT_ARGS(pfaReturn,    AT_Int,        &nReturn,    sizeof(nReturn)        );
  1999.     INIT_TF(tf, FN_GetHostName, 2, pfaArgs, pfaReturn);
  2000.     TransmitFunctionAndBlock(ppt, &tf);
  2001.     return nReturn;
  2002. }
  2003.  
  2004. int pascal far _export WSAStartup(WORD wVersionRequired, LPWSADATA lpWSAData)
  2005. {
  2006.     struct    per_task    *pptNew;
  2007.  
  2008.     lpWSAData->wVersion = 0x0101;
  2009.     lpWSAData->wHighVersion = 0x0101;
  2010.     strcpy(lpWSAData->szDescription,
  2011.         "TwinSock 1.4 - Proxy sockets system. "
  2012.         "Copyright 1994-1995 Troy Rollo. "
  2013.         "TwinSock is free software. "
  2014.         "See the file \"COPYING\" from the "
  2015.         "distribution for details.");
  2016.     if (!hwndManager)
  2017.         strcpy(lpWSAData->szSystemStatus, "Not Initialised.");
  2018.     else if (bEstablished)
  2019.         strcpy(lpWSAData->szSystemStatus, "Ready.");
  2020.     else
  2021.         strcpy(lpWSAData->szSystemStatus, "Initialising.");
  2022.     lpWSAData->iMaxSockets = 256;
  2023.     lpWSAData->iMaxUdpDg = 512;
  2024.     lpWSAData->lpVendorInfo = 0;
  2025.     if (wVersionRequired == 0x0001)
  2026.         return WSAVERNOTSUPPORTED;
  2027.     if (!bEstablished)
  2028.         return WSASYSNOTREADY;
  2029.     pptNew = malloc(sizeof(struct per_task));
  2030.     if (pptNew == 0)
  2031.         return (WSAENOBUFS);
  2032.     pptNew->htask = GetCurrentTask();
  2033.     pptNew->pptNext = pptList;
  2034.     pptNew->lpBlockFunc = 0;
  2035.     pptNew->bCancel = FALSE;
  2036.     pptNew->bBlocking = FALSE;
  2037.     pptList = pptNew;
  2038.     return 0;
  2039. }
  2040.  
  2041. int pascal far _export WSACleanup(void)
  2042. {
  2043.     struct    per_task *ppt;
  2044.  
  2045.     if ((ppt = GetTaskInfo()) == 0)
  2046.         return -1;
  2047.     if (ppt->bBlocking)
  2048.     {
  2049.         iErrno = WSAEINPROGRESS;
  2050.         return -1;
  2051.     }
  2052.     RemoveTask(ppt);
  2053.     return 0;
  2054. }
  2055.  
  2056. void pascal far _export WSASetLastError(int iError)
  2057. {
  2058.     if (!GetTaskInfo())
  2059.         return;
  2060.     iErrno = iError;
  2061. }
  2062.  
  2063. int pascal far _export WSAGetLastError(void)
  2064. {
  2065.     return iErrno;
  2066. }
  2067.  
  2068. BOOL pascal far _export WSAIsBlocking(void)
  2069. {
  2070.     struct per_task *ppt;
  2071.  
  2072.     if ((ppt = GetTaskInfo()) == 0)
  2073.         return -1;
  2074.     return ppt->bBlocking;
  2075. }
  2076.  
  2077. int pascal far _export WSAUnhookBlockingHook(void)
  2078. {
  2079.     struct    per_task *ppt;
  2080.  
  2081.     if ((ppt = GetTaskInfo()) == 0)
  2082.         return -1;
  2083.     ppt->lpBlockFunc = 0;
  2084.     return 0;
  2085. }
  2086.  
  2087. FARPROC pascal far _export WSASetBlockingHook(FARPROC lpBlockFunc)
  2088. {
  2089.     struct per_task *ppt;
  2090.     FARPROC oldfunc;
  2091.     
  2092.     if ((ppt = GetTaskInfo()) == 0)
  2093.         return 0;
  2094.     oldfunc = ppt->lpBlockFunc;
  2095.     ppt->lpBlockFunc = lpBlockFunc;
  2096.  
  2097.     return (oldfunc);    /* Return the previous value */
  2098. }
  2099.  
  2100. int pascal far _export WSACancelBlockingCall(void)
  2101. {
  2102.     struct    per_task *ppt;
  2103.  
  2104.     if ((ppt = GetTaskInfo()) == 0)
  2105.         return -1;
  2106.     if (ppt->bBlocking)
  2107.     {
  2108.         ppt->bCancel = TRUE;
  2109.         return 0;
  2110.     }
  2111.     else
  2112.     {
  2113.         iErrno = WSAEINVAL;
  2114.         return -1;
  2115.     }
  2116. }
  2117.  
  2118. static    void
  2119. FireAsyncRequest(struct tx_queue *ptxq)
  2120. {
  2121.     int    nLen;
  2122.     char    *pchData;
  2123.     struct    per_task *ppt;
  2124.  
  2125.     if (ptxq->ptxr->nError)
  2126.     {
  2127.         PostMessage(ptxq->hwnd, ptxq->wMsg, ptxq->id | 0x4000,
  2128.             WSAMAKEASYNCREPLY(0, ntohs(ptxq->ptxr->nError)));
  2129.         RemoveTXQ(ptxq);
  2130.         return;
  2131.     }
  2132.  
  2133.     ppt = GetAnotherTaskInfo(ptxq->htask);
  2134.  
  2135.     if (!ppt)
  2136.     {
  2137.         /* How **Rude** */
  2138.         RemoveTXQ(ptxq);
  2139.         return;
  2140.     }
  2141.  
  2142.     pchData = ptxq->ptxr->pchData +
  2143.         ntohs(ptxq->ptxr->nLen) -
  2144.         MAX_HOST_ENT -
  2145.         sizeof(short) * 5;
  2146.  
  2147.     switch(ptxq->ft)
  2148.     {
  2149.     case FN_HostByName:
  2150.     case FN_HostByAddr:
  2151.         memcpy(ppt->achHostEnt, pchData, MAX_HOST_ENT);
  2152.         nLen = CopyHostEntTo(ppt, ptxq->pchLocation);
  2153.         break;
  2154.  
  2155.     case FN_ServByName:
  2156.     case FN_ServByPort:
  2157.         memcpy(ppt->achServEnt, pchData, MAX_HOST_ENT);
  2158.         nLen = CopyServEntTo(ppt, ptxq->pchLocation);
  2159.         break;
  2160.  
  2161.     case FN_ProtoByName:
  2162.     case FN_ProtoByNumber:
  2163.         memcpy(ppt->achProtoEnt, pchData, MAX_HOST_ENT);
  2164.         nLen = CopyProtoEntTo(ppt, ptxq->pchLocation);
  2165.         break;
  2166.     }
  2167.  
  2168.     PostMessage(ptxq->hwnd, ptxq->wMsg, ptxq->id | 0x4000,
  2169.         WSAMAKEASYNCREPLY(nLen, 0));
  2170.     RemoveTXQ(ptxq);
  2171. }
  2172.  
  2173. HANDLE pascal far _export WSAAsyncGetServByName(HWND hWnd, u_int wMsg,
  2174.                                         const char FAR * name,
  2175.                     const char FAR * proto,
  2176.                                         char FAR * buf, int buflen)
  2177. {
  2178.     struct per_task *ppt;
  2179.     struct    func_arg pfaArgs[2];
  2180.     struct    func_arg pfaReturn;
  2181.     struct    transmit_function tf;
  2182.     struct    tx_queue *txq;
  2183.  
  2184.     if ((ppt = GetTaskInfo()) == 0)
  2185.         return 0;
  2186.     if (!proto)
  2187.         proto = "";
  2188.     INIT_CARGS(pfaArgs[0],    AT_String,    name,        strlen(name) + 1    );
  2189.     INIT_CARGS(pfaArgs[1],    AT_String,    proto,        strlen(proto) + 1    );
  2190.     INIT_ARGS(pfaReturn,    AT_GenPtr,    ppt->achServEnt,MAX_HOST_ENT        );
  2191.     INIT_TF(tf, FN_ServByName, 2, pfaArgs, pfaReturn);
  2192.     txq = TransmitFunction(&tf);
  2193.     txq->hwnd = hWnd;
  2194.     txq->pchLocation = buf;
  2195.     txq->wMsg = wMsg;
  2196.     txq->ft = FN_ServByName;
  2197.     txq->htask = ppt->htask;
  2198.     return (txq->id | 0x4000);
  2199. }
  2200.  
  2201. HANDLE pascal far _export WSAAsyncGetServByPort(HWND hWnd, u_int wMsg, int port,
  2202.                                         const char FAR * proto, char FAR * buf,
  2203.                                         int buflen)
  2204. {
  2205.     struct per_task *ppt;
  2206.     struct    func_arg pfaArgs[2];
  2207.     struct    func_arg pfaReturn;
  2208.     struct    transmit_function tf;
  2209.     struct    tx_queue *txq;
  2210.  
  2211.     if ((ppt = GetTaskInfo()) == 0)
  2212.         return 0;
  2213.     port = PORTSWAP(port);
  2214.     if (!proto)
  2215.         proto = "";
  2216.     INIT_CARGS(pfaArgs[0],    AT_Int,        &port,        sizeof(port)        );
  2217.     INIT_CARGS(pfaArgs[1],    AT_String,    proto,        strlen(proto) + 1    );
  2218.     INIT_ARGS(pfaReturn,    AT_GenPtr,    ppt->achServEnt,MAX_HOST_ENT        );
  2219.     INIT_TF(tf, FN_ServByPort, 2, pfaArgs, pfaReturn);
  2220.     txq = TransmitFunction(&tf);
  2221.     txq->hwnd = hWnd;
  2222.     txq->pchLocation = buf;
  2223.     txq->wMsg = wMsg;
  2224.     txq->ft = FN_ServByPort;
  2225.     txq->htask = ppt->htask;
  2226.     return (txq->id | 0x4000);
  2227. }
  2228.  
  2229. HANDLE pascal far _export WSAAsyncGetProtoByName(HWND hWnd, u_int wMsg,
  2230.                                          const char FAR * name, char FAR * buf,
  2231.                                          int buflen)
  2232. {
  2233.     struct per_task *ppt;
  2234.     struct    func_arg pfaArgs[1];
  2235.     struct    func_arg pfaReturn;
  2236.     struct    transmit_function tf;
  2237.     struct    tx_queue *txq;
  2238.  
  2239.     if ((ppt = GetTaskInfo()) == 0)
  2240.         return 0;
  2241.     INIT_CARGS(pfaArgs[0],    AT_String,    name,        strlen(name) + 1    );
  2242.     INIT_ARGS(pfaReturn,    AT_GenPtr,    ppt->achProtoEnt,MAX_HOST_ENT        );
  2243.     INIT_TF(tf, FN_ProtoByName, 1, pfaArgs, pfaReturn);
  2244.     txq = TransmitFunction(&tf);
  2245.     txq->hwnd = hWnd;
  2246.     txq->pchLocation = buf;
  2247.     txq->wMsg = wMsg;
  2248.     txq->ft = FN_ProtoByName;
  2249.     txq->htask = ppt->htask;
  2250.     return (txq->id | 0x4000);
  2251. }
  2252.  
  2253. HANDLE pascal far _export WSAAsyncGetProtoByNumber(HWND hWnd, u_int wMsg,
  2254.                                            int number, char FAR * buf,
  2255.                                            int buflen)
  2256. {
  2257.     struct per_task *ppt;
  2258.     struct    func_arg pfaArgs[1];
  2259.     struct    func_arg pfaReturn;
  2260.     struct    transmit_function tf;
  2261.     struct    tx_queue *txq;
  2262.  
  2263.     if ((ppt = GetTaskInfo()) == 0)
  2264.         return 0;
  2265.     INIT_CARGS(pfaArgs[0],    AT_Int,        &number,    sizeof(number)        );
  2266.     INIT_ARGS(pfaReturn,    AT_GenPtr,    ppt->achProtoEnt,MAX_HOST_ENT        );
  2267.     INIT_TF(tf, FN_ProtoByNumber, 1, pfaArgs, pfaReturn);
  2268.     txq = TransmitFunction(&tf);
  2269.     txq->hwnd = hWnd;
  2270.     txq->pchLocation = buf;
  2271.     txq->wMsg = wMsg;
  2272.     txq->ft = FN_ProtoByNumber;
  2273.     txq->htask = ppt->htask;
  2274.     return (txq->id | 0x4000);
  2275. }
  2276.  
  2277. HANDLE pascal far _export WSAAsyncGetHostByName(HWND hWnd, u_int wMsg,
  2278.                                         const char FAR * name, char FAR * buf,
  2279.                                         int buflen)
  2280. {
  2281.     struct per_task *ppt;
  2282.     struct    func_arg pfaArgs[1];
  2283.     struct    func_arg pfaReturn;
  2284.     struct    transmit_function tf;
  2285.     struct    tx_queue *txq;
  2286.  
  2287.     if ((ppt = GetTaskInfo()) == 0)
  2288.         return 0;
  2289.     INIT_CARGS(pfaArgs[0],    AT_GenPtr,    name,        strlen(name) + 1    );
  2290.     INIT_ARGS(pfaReturn,    AT_GenPtr,    ppt->achHostEnt,MAX_HOST_ENT        );
  2291.     INIT_TF(tf, FN_HostByName, 1, pfaArgs, pfaReturn);
  2292.     txq = TransmitFunction(&tf);
  2293.     txq->hwnd = hWnd;
  2294.     txq->pchLocation = buf;
  2295.     txq->wMsg = wMsg;
  2296.     txq->ft = FN_HostByName;
  2297.     txq->htask = ppt->htask;
  2298.     return (txq->id | 0x4000);
  2299. }
  2300.  
  2301. HANDLE pascal far _export WSAAsyncGetHostByAddr(HWND hWnd, u_int wMsg,
  2302.                                         const char FAR * addr, int len, int type,
  2303.                                         char FAR * buf, int buflen)
  2304. {
  2305.     struct per_task *ppt;
  2306.     struct    func_arg pfaArgs[3];
  2307.     struct    func_arg pfaReturn;
  2308.     struct    transmit_function tf;
  2309.     struct    tx_queue *txq;
  2310.  
  2311.     if ((ppt = GetTaskInfo()) == 0)
  2312.         return 0;
  2313.     INIT_CARGS(pfaArgs[0],    AT_GenPtr,    addr,        len            );
  2314.     INIT_CARGS(pfaArgs[1],    AT_Int,        &len,        sizeof(len)        );
  2315.     INIT_CARGS(pfaArgs[2],    AT_Int,        &type,        sizeof(type)        );
  2316.     INIT_ARGS(pfaReturn,    AT_GenPtr,    ppt->achHostEnt,MAX_HOST_ENT        );
  2317.     INIT_TF(tf, FN_HostByAddr, 3, pfaArgs, pfaReturn);
  2318.     txq = TransmitFunction(&tf);
  2319.     txq->hwnd = hWnd;
  2320.     txq->pchLocation = buf;
  2321.     txq->wMsg = wMsg;
  2322.     txq->ft = FN_HostByAddr;
  2323.     txq->htask = ppt->htask;
  2324.     return (txq->id | 0x4000);
  2325. }
  2326.  
  2327. int pascal far _export WSACancelAsyncRequest(HANDLE hAsyncTaskHandle)
  2328. {
  2329.     struct    tx_queue *ptxq;
  2330.  
  2331.     if (!GetTaskInfo())
  2332.         return -1;
  2333.  
  2334.     for (ptxq = ptxqList; ptxq; ptxq = ptxq->ptxqNext)
  2335.     {
  2336.         if ((HANDLE) (ptxq->id | 0x4000) == hAsyncTaskHandle)
  2337.         {
  2338.             RemoveTXQ(ptxq);
  2339.             return 0;
  2340.         }
  2341.     }
  2342.     iErrno = WSAEINVAL;
  2343.     return -1;
  2344. }
  2345.  
  2346. int pascal far _export WSAAsyncSelect(SOCKET s, HWND hWnd, u_int wMsg,
  2347.                                long lEvent)
  2348. {
  2349.     struct    per_task *ppt;
  2350.     struct    per_socket *pps;
  2351.  
  2352.     if ((ppt = GetTaskInfo()) == 0)
  2353.         return -1;
  2354.     if ((pps = GetSocketInfo(s)) == 0)
  2355.         return -1;
  2356.     if (lEvent)
  2357.         pps->iFlags |= PSF_NONBLOCK;
  2358.     pps->hWnd = hWnd;
  2359.     pps->wMsg = wMsg;
  2360.     pps->iEvents = lEvent;
  2361.     if (!(pps->iFlags & PSF_MUSTCONN) ||
  2362.         (pps->iFlags & PSF_CONNECT))
  2363.         Notify(pps, FD_WRITE);
  2364.     if (pps->pdIn)
  2365.         Notify(pps, (pps->iFlags & PSF_ACCEPT) ?
  2366.                 FD_ACCEPT :
  2367.                 (pps->pdIn->iLen ?
  2368.                     FD_READ :
  2369.                     FD_CLOSE));
  2370.     return 0;
  2371. }
  2372.  
  2373. int FAR PASCAL _export __WSAFDIsSet(SOCKET s, fd_set FAR *pfds)
  2374. {
  2375.     u_short    i;
  2376.  
  2377.     if (!GetTaskInfo())
  2378.         return -1;
  2379.     if (!GetSocketInfo(s))
  2380.         return -1;
  2381.     for (i = 0; i < pfds->fd_count; i++)
  2382.     {
  2383.         if (pfds->fd_array[i] == s)
  2384.             return TRUE;
  2385.     }
  2386.     return FALSE;
  2387. }
  2388.  
  2389.  
  2390.