xref: /reactos/dll/win32/ws2_32/src/enumprot.c (revision 845faec4)
1 /*
2  * COPYRIGHT:   See COPYING in the top level directory
3  * PROJECT:     ReactOS WinSock 2 API
4  * FILE:        dll/win32/ws2_32_new/src/enumprot.c
5  * PURPOSE:     Protocol Enumeration
6  * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
7  */
8 
9 /* INCLUDES ******************************************************************/
10 
11 #include <ws2_32.h>
12 
13 #define NDEBUG
14 #include <debug.h>
15 
16 /* FUNCTIONS *****************************************************************/
17 
18 BOOL
19 WSAAPI
20 CheckProtocolMatch(IN LPINT ProtocolSet,
21                    IN LPWSAPROTOCOL_INFOW ProtocolInfo)
22 {
23     BOOL Return = FALSE;
24     DWORD i = 0;
25     INT ProtocolId;
26 
27     /* Make sure we have a set */
28     if (ProtocolSet)
29     {
30         /* Get the first ID */
31         ProtocolId = ProtocolSet[i];
32 
33         /* Loop the list */
34         while (ProtocolId != 0 && ProtocolInfo->iProtocol != 0)
35         {
36             /* Check if it's within ranges */
37             if ((ProtocolId >= ProtocolInfo->iProtocol) &&
38                 (ProtocolId <= (ProtocolInfo->iProtocol +
39                                 ProtocolInfo->iProtocolMaxOffset)))
40             {
41                 /* Found it */
42                 Return = TRUE;
43                 break;
44             }
45 
46             /* Move on */
47             i++;
48             ProtocolId = ProtocolSet[i];
49         }
50     }
51     else
52     {
53         /* Assume match */
54         Return = TRUE;
55     }
56 
57     /* Return result */
58     return Return;
59 }
60 
61 VOID
62 WSAAPI
63 ProtocolInfoFromContext(IN LPWSAPROTOCOL_INFOW ProtocolInfo,
64                         IN PPROTOCOL_ENUM_CONTEXT Context)
65 {
66     /* Check if we'll have space */
67     if ((Context->BufferUsed + sizeof(*ProtocolInfo)) <=
68         (Context->BufferLength))
69     {
70         /* Copy the data */
71         RtlMoveMemory((PVOID)((ULONG_PTR)Context->ProtocolBuffer +
72                               Context->BufferUsed),
73                       ProtocolInfo,
74                       sizeof(*ProtocolInfo));
75 
76         /* Increase the count */
77         Context->Count++;
78     }
79 }
80 
81 BOOL
82 WSAAPI
83 ProtocolEnumerationProc(PVOID EnumContext,
84                         PTCATALOG_ENTRY Entry)
85 {
86     PPROTOCOL_ENUM_CONTEXT Context = (PPROTOCOL_ENUM_CONTEXT)EnumContext;
87     LPWSAPROTOCOL_INFOW ProtocolInfo = &Entry->ProtocolInfo;
88 
89     /* Check if this protocol matches */
90     if (CheckProtocolMatch(Context->Protocols, ProtocolInfo))
91     {
92         /* Copy the information */
93         ProtocolInfoFromContext(ProtocolInfo, Context);
94         Context->BufferUsed += sizeof(*ProtocolInfo);
95     }
96 
97     /* Continue enumeration */
98     return TRUE;
99 }
100 
101 PTCATALOG
102 WSAAPI
103 OpenInitializedCatalog(VOID)
104 {
105     PTCATALOG Catalog;
106     HKEY WsKey;
107 
108     /* Allocate the catalog */
109     Catalog = WsTcAllocate();
110     if (Catalog)
111     {
112         /* Open the WS Key */
113         WsKey = WsOpenRegistryRoot();
114 
115         /* Initialize the catalog */
116         WsTcInitializeFromRegistry(Catalog, WsKey, NULL);
117 
118         /* Close the key */
119         RegCloseKey(WsKey);
120     }
121 
122     /* Return it */
123     return Catalog;
124 }
125 
126 /*
127  * @implemented
128  */
129 INT
130 WSPAPI
131 WSCEnumProtocols(IN LPINT lpiProtocols,
132                  OUT LPWSAPROTOCOL_INFOW lpProtocolBuffer,
133                  IN OUT LPDWORD lpdwBufferLength,
134                  OUT LPINT lpErrno)
135 {
136     INT Status;
137     PTCATALOG Catalog;
138     PROTOCOL_ENUM_CONTEXT Context;
139     DPRINT("WSCEnumProtocols: %p\n", lpiProtocols);
140 
141     /* Create a catalog object from the current one */
142     Catalog = OpenInitializedCatalog();
143     if (!Catalog)
144     {
145         /* Fail if we couldn't */
146         *lpErrno = WSAENOBUFS;
147         return SOCKET_ERROR;
148     }
149 
150     /* Setup the context */
151     Context.Protocols = lpiProtocols;
152     Context.ProtocolBuffer = lpProtocolBuffer;
153     Context.BufferLength = lpProtocolBuffer ? *lpdwBufferLength : 0;
154     Context.BufferUsed = 0;
155     Context.Count = 0;
156     Context.ErrorCode = ERROR_SUCCESS;
157 
158     /* Enumerate the catalog */
159     WsTcEnumerateCatalogItems(Catalog, ProtocolEnumerationProc, &Context);
160 
161     /* Get status */
162     Status = Context.Count;
163 
164     /* Check the error code */
165     if (Context.ErrorCode == ERROR_SUCCESS)
166     {
167         /* Check if enough space was available */
168         if (Context.BufferLength < Context.BufferUsed)
169         {
170             /* Fail and tell them how much we need */
171             *lpdwBufferLength = Context.BufferUsed;
172             *lpErrno = WSAENOBUFS;
173             Status = SOCKET_ERROR;
174         }
175     }
176     else
177     {
178         /* Failure, normalize error */
179         Status = SOCKET_ERROR;
180         *lpErrno = Context.ErrorCode;
181     }
182 
183     /* Delete the catalog object */
184     WsTcDelete(Catalog);
185 
186     /* Return */
187     return Status;
188 }
189 
190 /*
191  * @implemented
192  */
193 INT
194 WSAAPI
195 WSAEnumProtocolsA(IN LPINT lpiProtocols,
196                   OUT LPWSAPROTOCOL_INFOA lpProtocolBuffer,
197                   IN OUT LPDWORD lpdwBufferLength)
198 {
199     INT error, i, count;
200     LPWSAPROTOCOL_INFOW protocolInfoW;
201     DWORD size;
202     DPRINT("WSAEnumProtocolsA: %p %p %p\n", lpiProtocols, lpProtocolBuffer, lpdwBufferLength);
203     if (!lpdwBufferLength)
204     {
205         SetLastError(WSAENOBUFS);
206         return SOCKET_ERROR;
207     }
208     count = WSCEnumProtocols(lpiProtocols, NULL, &size, &error);
209     if (!lpProtocolBuffer || *lpdwBufferLength < (size/sizeof(WSAPROTOCOL_INFOW))*sizeof(WSAPROTOCOL_INFOA))
210     {
211         *lpdwBufferLength = (size/sizeof(WSAPROTOCOL_INFOW))*sizeof(WSAPROTOCOL_INFOA);
212         SetLastError(WSAENOBUFS);
213         return SOCKET_ERROR;
214     }
215     protocolInfoW = HeapAlloc(WsSockHeap, 0, size);
216     count = WSCEnumProtocols(lpiProtocols, protocolInfoW, &size, &error);
217     if (SOCKET_ERROR == count)
218     {
219         HeapFree(WsSockHeap, 0, protocolInfoW);
220         SetLastError(error);
221         return SOCKET_ERROR;
222     }
223     *lpdwBufferLength = 0;
224     for (i = 0; i < count; i++)
225     {
226         /* Copy the data */
227         RtlMoveMemory(&lpProtocolBuffer[i],
228                       &protocolInfoW[i],
229                       sizeof(lpProtocolBuffer[0])-sizeof(lpProtocolBuffer[0].szProtocol));
230         wcstombs(lpProtocolBuffer[i].szProtocol, protocolInfoW[i].szProtocol, sizeof(lpProtocolBuffer[0].szProtocol));
231         *lpdwBufferLength += sizeof(WSAPROTOCOL_INFOA);
232     }
233     HeapFree(WsSockHeap, 0, protocolInfoW);
234     return i;
235 }
236 
237 /*
238  * @implemented
239  */
240 INT
241 WSAAPI
242 WSAEnumProtocolsW(IN LPINT lpiProtocols,
243                   OUT LPWSAPROTOCOL_INFOW lpProtocolBuffer,
244                   IN OUT  LPDWORD lpdwBufferLength)
245 {
246     INT error, count;
247     DPRINT("WSAEnumProtocolsW: %p %p %p\n", lpiProtocols, lpProtocolBuffer, lpdwBufferLength);
248     count = WSCEnumProtocols(lpiProtocols, lpProtocolBuffer, lpdwBufferLength, &error);
249     if (SOCKET_ERROR == count)
250     {
251         SetLastError(error);
252         return SOCKET_ERROR;
253     }
254     return count;
255 }
256 
257 
258 /*
259  * @implemented
260  */
261 INT
262 WSPAPI
263 WPUGetProviderPath(IN LPGUID lpProviderId,
264                    OUT LPWSTR lpszProviderDllPath,
265                    IN OUT LPINT lpProviderDllPathLen,
266                    OUT LPINT lpErrno)
267 {
268     return WSCGetProviderPath(lpProviderId, lpszProviderDllPath, lpProviderDllPathLen, lpErrno);
269 }
270 
271 /*
272  * @implemented
273  */
274 INT
275 WSAAPI
276 WSAProviderConfigChange(IN OUT LPHANDLE lpNotificationHandle,
277                         IN LPWSAOVERLAPPED lpOverlapped,
278                         IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
279 {
280     DPRINT("WSAProviderConfigChange: %p\n", lpNotificationHandle);
281     UNIMPLEMENTED;
282     SetLastError(WSAEINVAL);
283     return SOCKET_ERROR;
284 }
285 
286 /*
287  * @unimplemented
288  */
289 INT
290 WSPAPI
291 WSCGetProviderPath(IN LPGUID lpProviderId,
292                    OUT LPWSTR lpszProviderDllPath,
293                    IN OUT LPINT lpProviderDllPathLen,
294                    OUT LPINT lpErrno)
295 {
296     DPRINT("WSCGetProviderPath: %p %p %p %p\n", lpProviderId, lpszProviderDllPath, lpProviderDllPathLen, lpErrno);
297     UNIMPLEMENTED;
298     SetLastError(WSAEINVAL);
299     return SOCKET_ERROR;
300 }
301