home *** CD-ROM | disk | FTP | other *** search
/ Borland Programmer's Resource / Borland_Programmers_Resource_CD_1995.iso / winsock / twnsck10 / winsock.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-19  |  46.5 KB  |  1,997 lines

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