xref: /reactos/dll/win32/ws2_32/src/dsocket.c (revision 1734f297)
1 /*
2  * COPYRIGHT:   See COPYING in the top level directory
3  * PROJECT:     ReactOS WinSock 2 API
4  * FILE:        dll/win32/ws2_32/src/dsocket.c
5  * PURPOSE:     Socket Object
6  * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
7  */
8 
9 /* INCLUDES ******************************************************************/
10 
11 #include <ws2_32.h>
12 
13 /* DATA **********************************************************************/
14 
15 PWAH_HANDLE_TABLE WsSockHandleTable;
16 
17 /* FUNCTIONS *****************************************************************/
18 
19 INT
20 WSAAPI
21 WsSockStartup(VOID)
22 {
23     /* Check if we have a socket table */
24     if (!WsSockHandleTable)
25     {
26         /* Create it */
27         return WahCreateHandleContextTable(&WsSockHandleTable);
28     }
29 
30     /* Nothing to do */
31     return NO_ERROR;
32 }
33 
34 VOID
35 WSPAPI
36 WsSockCleanup(VOID)
37 {
38     /* Check if we have a socket table */
39     if (WsSockHandleTable)
40     {
41         /* Destroy it */
42         WahDestroyHandleContextTable(WsSockHandleTable);
43     }
44 }
45 
46 PWSSOCKET
47 WSAAPI
48 WsSockAllocate(VOID)
49 {
50     PWSSOCKET Socket;
51 
52     /* Allocate the socket object */
53     Socket = HeapAlloc(WsSockHeap, HEAP_ZERO_MEMORY, sizeof(*Socket));
54     if (Socket)
55     {
56         /* Setup default non-zero values */
57         Socket->RefCount = 2;
58         Socket->Overlapped = TRUE;
59     }
60 
61     /* Return it */
62     return Socket;
63 }
64 
65 INT
66 WSAAPI
67 WsSockInitialize(IN PWSSOCKET Socket,
68                  IN PTCATALOG_ENTRY CatalogEntry)
69 {
70     PWSTHREAD CurrentThread;
71 
72     /* Associate this catalog and reference it */
73     Socket->CatalogEntry = CatalogEntry;
74     InterlockedIncrement(&CatalogEntry->RefCount);
75 
76     /* Associate the Provider and Process Objects */
77     Socket->Provider = CatalogEntry->Provider;
78 
79     /* Get the current Thread Object */
80     if ((CurrentThread = TlsGetValue(TlsIndex)))
81     {
82         /* Set the overlapped mode */
83         Socket->Overlapped = (CurrentThread->OpenType == 0);
84     }
85 
86     /* Return status */
87     return ERROR_SUCCESS;
88 }
89 
90 PWSSOCKET
91 WSAAPI
92 WsSockGetSocketNoExport(IN SOCKET Handle)
93 {
94     /* Let WAH do the translation */
95     return (PWSSOCKET)WahReferenceContextByHandle(WsSockHandleTable,
96                                                   (HANDLE)Handle);
97 }
98 
99 PWSSOCKET
100 WSAAPI
101 WsSockFindIfsSocket(IN SOCKET Handle)
102 {
103     INT ErrorCode;
104     DWORD Flags;
105     PWSSOCKET Socket = NULL;
106     PWSPROCESS Process = NULL;
107     PTCATALOG Catalog = NULL;
108 
109     /* Validate the socket and get handle info */
110     if ((Handle != INVALID_SOCKET) &&
111         (GetHandleInformation((HANDLE)Handle, &Flags)))
112     {
113         /* Get the process */
114         if ((Process = WsGetProcess()))
115         {
116             /* Get the catalog */
117             Catalog = WsProcGetTCatalog(Process);
118 
119             /* Get the IFS Provider */
120             ErrorCode = WsTcFindIfsProviderForSocket(Catalog, Handle);
121 
122             /* Check for success */
123             if (ErrorCode == ERROR_SUCCESS)
124             {
125                 /* Get the Socket now */
126                 Socket = WsSockGetSocketNoExport(Handle);
127 
128                 /* Mark it as an API Socket */
129                 if (Socket) Socket->ApiSocket = TRUE;
130             }
131         }
132     }
133 
134     /* Return the socket */
135     return Socket;
136 }
137 
138 PWSSOCKET
139 WSAAPI
140 WsSockGetSocket(IN SOCKET Handle)
141 {
142     PWSSOCKET Socket;
143 
144     /* Let WAH do the translation */
145     if ((WsSockHandleTable != NULL) &&
146         (Socket = (PWSSOCKET)WahReferenceContextByHandle(WsSockHandleTable, (HANDLE)Handle)))
147     {
148         return Socket;
149     }
150     else
151     {
152         /* WAH didn't find it, use IFS */
153         return WsSockFindIfsSocket(Handle);
154     }
155 }
156 
157 INT
158 WSAAPI
159 WsSockAddApiReference(IN SOCKET Handle)
160 {
161     PWSSOCKET Socket;
162 
163     /* Get the Socket now */
164     if ((Socket = WsSockGetSocketNoExport(Handle)))
165     {
166         /* Mark it as an API Socket */
167         if (Socket) Socket->ApiSocket = TRUE;
168 
169         /* Remove a reference and return */
170         WsSockDereference(Socket);
171         return ERROR_SUCCESS;
172     }
173 
174     /* Return error */
175     return WSASYSCALLFAILURE;
176 }
177 
178 BOOL
179 WSAAPI
180 WsSockDeleteSockets(IN LPVOID Context,
181                     IN PWAH_HANDLE Handle)
182 {
183     /* Call the detach routine */
184     return WsProcDetachSocket((PWSPROCESS)Context, Handle);
185 }
186 
187 VOID
188 WSAAPI
189 WsSockDelete(IN PWSSOCKET Socket)
190 {
191     /* Check if we have a catalog entry */
192     if (Socket->CatalogEntry)
193     {
194         /* Dereference it */
195         WsTcEntryDereference(Socket->CatalogEntry);
196         Socket->CatalogEntry = NULL;
197     }
198 
199     /* Delete us */
200     HeapFree(WsSockHeap, 0, Socket);
201 }
202 
203 VOID
204 WSAAPI
205 WsSockDereference(IN PWSSOCKET Socket)
206 {
207     /* Dereference and check if it's now 0 */
208     if (!(InterlockedDecrement(&Socket->RefCount)))
209     {
210         /* We can delete the Provider now */
211         WsSockDelete(Socket);
212     }
213 }
214 
215 INT
216 WSAAPI
217 WsSockDisassociateHandle(IN PWSSOCKET Socket)
218 {
219     /* Remove it from the list */
220     return WahRemoveHandleContext(WsSockHandleTable, (PWAH_HANDLE)Socket);
221 }
222 
223 INT
224 WSAAPI
225 WsSockAssociateHandle(IN PWSSOCKET Socket,
226                       IN SOCKET Handle,
227                       IN BOOLEAN IsProvider)
228 {
229     INT ErrorCode = ERROR_SUCCESS;
230     PWSSOCKET OldSocket;
231 
232     /* Save the socket and provider */
233     Socket->IsProvider = IsProvider;
234     Socket->Handle = (HANDLE)Handle;
235 
236     /* Insert it into the handle table */
237     OldSocket = (PWSSOCKET)WahInsertHandleContext(WsSockHandleTable,
238                                                   (PWAH_HANDLE)Socket);
239 
240     /* Check if a socket already existed */
241     if (OldSocket != Socket)
242     {
243         /* We'll dereference it */
244         WsSockDereference(OldSocket);
245     }
246     else if (!OldSocket)
247     {
248         /* No memory to allocate it */
249         ErrorCode = WSAENOBUFS;
250     }
251 
252     /* Return */
253     return ErrorCode;
254 }
255