1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
/*
 * COPYRIGHT:   See COPYING in the top level directory
 * PROJECT:     ReactOS WinSock 2 API
 * FILE:        dll/win32/ws2_32_new/src/dsocket.c
 * PURPOSE:     Socket Object
 * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
 */

/* INCLUDES ******************************************************************/

#include <ws2_32.h>

/* DATA **********************************************************************/

PWAH_HANDLE_TABLE WsSockHandleTable;

/* FUNCTIONS *****************************************************************/

INT
WSAAPI
WsSockStartup(VOID)
{
    /* Check if we have a socket table */
    if (!WsSockHandleTable)
    {
        /* Create it */
        return WahCreateHandleContextTable(&WsSockHandleTable);
    }

    /* Nothing to do */
    return NO_ERROR;
}

VOID
WSPAPI
WsSockCleanup(VOID)
{
    /* Check if we have a socket table */
    if (WsSockHandleTable)
    {
        /* Destroy it */
        WahDestroyHandleContextTable(WsSockHandleTable);
    }
}

PWSSOCKET
WSAAPI
WsSockAllocate(VOID)
{
    PWSSOCKET Socket;

    /* Allocate the socket object */
    Socket = HeapAlloc(WsSockHeap, HEAP_ZERO_MEMORY, sizeof(*Socket));
    if (Socket)
    {
        /* Setup default non-zero values */
        Socket->RefCount = 2;
        Socket->Overlapped = TRUE;
    }

    /* Return it */
    return Socket;
}

INT
WSAAPI
WsSockInitialize(IN PWSSOCKET Socket,
                 IN PTCATALOG_ENTRY CatalogEntry)
{
    PWSTHREAD CurrentThread;

    /* Associate this catalog and reference it */
    Socket->CatalogEntry = CatalogEntry;
    InterlockedIncrement(&CatalogEntry->RefCount);

    /* Associate the Provider and Process Objects */
    Socket->Provider = CatalogEntry->Provider;

    /* Get the current Thread Object */
    if ((CurrentThread = TlsGetValue(TlsIndex)))
    {
        /* Set the overlapped mode */
        Socket->Overlapped = (CurrentThread->OpenType == 0);
    }

    /* Return status */
    return ERROR_SUCCESS;
}

PWSSOCKET
WSAAPI
WsSockGetSocketNoExport(IN SOCKET Handle)
{
    /* Let WAH do the translation */
    return (PWSSOCKET)WahReferenceContextByHandle(WsSockHandleTable,
                                                  (HANDLE)Handle);
}

PWSSOCKET
WSAAPI
WsSockFindIfsSocket(IN SOCKET Handle)
{
    INT ErrorCode;
    DWORD Flags;
    PWSSOCKET Socket = NULL;
    PWSPROCESS Process = NULL;
    PTCATALOG Catalog = NULL;

    /* Validate the socket and get handle info */
    if ((Handle != INVALID_SOCKET) &&
        (GetHandleInformation((HANDLE)Handle, &Flags)))
    {
        /* Get the process */
        if ((Process = WsGetProcess()))
        {
            /* Get the catalog */
            Catalog = WsProcGetTCatalog(Process);

            /* Get the IFS Provider */
            ErrorCode = WsTcFindIfsProviderForSocket(Catalog, Handle);

            /* Check for success */
            if (ErrorCode == ERROR_SUCCESS)
            {
                /* Get the Socket now */
                Socket = WsSockGetSocketNoExport(Handle);

                /* Mark it as an API Socket */
                if (Socket) Socket->ApiSocket = TRUE;
            }
        }
    }

    /* Return the socket */
    return Socket;
}

PWSSOCKET
WSAAPI
WsSockGetSocket(IN SOCKET Handle)
{
    PWSSOCKET Socket;

    /* Let WAH do the translation */
    if ((Socket = (PWSSOCKET)WahReferenceContextByHandle(WsSockHandleTable,
                                                         (HANDLE)Handle)))
    {
        return Socket;
    }
    else
    {
        /* WAH didn't find it, use IFS */
        return WsSockFindIfsSocket(Handle);
    }
}

INT
WSAAPI
WsSockAddApiReference(IN SOCKET Handle)
{
    PWSSOCKET Socket;

    /* Get the Socket now */
    if ((Socket = WsSockGetSocketNoExport(Handle)))<--- Assuming that condition 'Socket=WsSockGetSocketNoExport(Handle)' is not redundant
    {
        /* Mark it as an API Socket */
        if (Socket) Socket->ApiSocket = TRUE;<--- Condition 'Socket' is always true

        /* Remove a reference and return */
        WsSockDereference(Socket);
        return ERROR_SUCCESS;
    }

    /* Return error */
    return WSASYSCALLFAILURE;
}

BOOL
WSAAPI
WsSockDeleteSockets(IN LPVOID Context,
                    IN PWAH_HANDLE Handle)
{
    /* Call the detach routine */
    return WsProcDetachSocket((PWSPROCESS)Context, Handle);
}

VOID
WSAAPI
WsSockDelete(IN PWSSOCKET Socket)
{
    /* Check if we have a catalog entry */
    if (Socket->CatalogEntry)
    {
        /* Dereference it */
        WsTcEntryDereference(Socket->CatalogEntry);
        Socket->CatalogEntry = NULL;
    }

    /* Delete us */
    HeapFree(WsSockHeap, 0, Socket);
}

VOID
WSAAPI
WsSockDereference(IN PWSSOCKET Socket)
{
    /* Dereference and check if it's now 0 */
    if (!(InterlockedDecrement(&Socket->RefCount)))
    {
        /* We can delete the Provider now */
        WsSockDelete(Socket);
    }
}

INT
WSAAPI
WsSockDisassociateHandle(IN PWSSOCKET Socket)
{
    /* Remove it from the list */
    return WahRemoveHandleContext(WsSockHandleTable, (PWAH_HANDLE)Socket);
}

INT
WSAAPI
WsSockAssociateHandle(IN PWSSOCKET Socket,
                      IN SOCKET Handle,
                      IN BOOLEAN IsProvider)
{
    INT ErrorCode = ERROR_SUCCESS;
    PWSSOCKET OldSocket;

    /* Save the socket and provider */
    Socket->IsProvider = IsProvider;
    Socket->Handle = (HANDLE)Handle;

    /* Insert it into the handle table */
    OldSocket = (PWSSOCKET)WahInsertHandleContext(WsSockHandleTable,
                                                  (PWAH_HANDLE)Socket);

    /* Check if a socket already existed */
    if (OldSocket != Socket)
    {
        /* We'll dereference it */
        WsSockDereference(OldSocket);
    }
    else if (!OldSocket)
    {
        /* No memory to allocate it */
        ErrorCode = WSAENOBUFS;
    }

    /* Return */
    return ErrorCode;
}