xref: /reactos/dll/win32/ws2_32/src/enumprot.c (revision 682f85ad)
1 /*
2  * COPYRIGHT:   See COPYING in the top level directory
3  * PROJECT:     ReactOS WinSock 2 API
4  * FILE:        dll/win32/ws2_32/src/enumprot.c
5  * PURPOSE:     Protocol Enumeration
6  * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
7  *              Pierre Schweitzer
8  */
9 
10 /* INCLUDES ******************************************************************/
11 
12 #include <ws2_32.h>
13 
14 #define NDEBUG
15 #include <debug.h>
16 
17 /* FUNCTIONS *****************************************************************/
18 
19 BOOL
20 WSAAPI
CheckProtocolMatch(IN LPINT ProtocolSet,IN LPWSAPROTOCOL_INFOW ProtocolInfo)21 CheckProtocolMatch(IN LPINT ProtocolSet,
22                    IN LPWSAPROTOCOL_INFOW ProtocolInfo)
23 {
24     BOOL Return = FALSE;
25     DWORD i = 0;
26     INT ProtocolId;
27 
28     /* Make sure we have a set */
29     if (ProtocolSet)
30     {
31         /* Get the first ID */
32         ProtocolId = ProtocolSet[i];
33 
34         /* Loop the list */
35         while (ProtocolId != 0 && ProtocolInfo->iProtocol != 0)
36         {
37             /* Check if it's within ranges */
38             if ((ProtocolId >= ProtocolInfo->iProtocol) &&
39                 (ProtocolId <= (ProtocolInfo->iProtocol +
40                                 ProtocolInfo->iProtocolMaxOffset)))
41             {
42                 /* Found it */
43                 Return = TRUE;
44                 break;
45             }
46 
47             /* Move on */
48             i++;
49             ProtocolId = ProtocolSet[i];
50         }
51     }
52     else
53     {
54         /* Assume match */
55         Return = TRUE;
56     }
57 
58     /* Return result */
59     return Return;
60 }
61 
62 VOID
63 WSAAPI
ProtocolInfoFromContext(IN LPWSAPROTOCOL_INFOW ProtocolInfo,IN PPROTOCOL_ENUM_CONTEXT Context)64 ProtocolInfoFromContext(IN LPWSAPROTOCOL_INFOW ProtocolInfo,
65                         IN PPROTOCOL_ENUM_CONTEXT Context)
66 {
67     /* Check if we'll have space */
68     if ((Context->BufferUsed + sizeof(*ProtocolInfo)) <=
69         (Context->BufferLength))
70     {
71         /* Copy the data */
72         RtlMoveMemory((PVOID)((ULONG_PTR)Context->ProtocolBuffer +
73                               Context->BufferUsed),
74                       ProtocolInfo,
75                       sizeof(*ProtocolInfo));
76 
77         /* Increase the count */
78         Context->Count++;
79     }
80 }
81 
82 BOOL
83 WSAAPI
ProtocolEnumerationProc(PVOID EnumContext,PTCATALOG_ENTRY Entry)84 ProtocolEnumerationProc(PVOID EnumContext,
85                         PTCATALOG_ENTRY Entry)
86 {
87     PPROTOCOL_ENUM_CONTEXT Context = (PPROTOCOL_ENUM_CONTEXT)EnumContext;
88     LPWSAPROTOCOL_INFOW ProtocolInfo = &Entry->ProtocolInfo;
89 
90     /* Check if this protocol matches */
91     if (CheckProtocolMatch(Context->Protocols, ProtocolInfo))
92     {
93         /* Copy the information */
94         ProtocolInfoFromContext(ProtocolInfo, Context);
95         Context->BufferUsed += sizeof(*ProtocolInfo);
96     }
97 
98     /* Continue enumeration */
99     return TRUE;
100 }
101 
102 BOOL
103 WSAAPI
ProviderEnumerationProc(PVOID EnumContext,PNSCATALOG_ENTRY Entry)104 ProviderEnumerationProc(PVOID EnumContext,
105                         PNSCATALOG_ENTRY Entry)
106 {
107     INT PathLen;
108     PPROVIDER_ENUM_CONTEXT Context = (PPROVIDER_ENUM_CONTEXT)EnumContext;
109 
110     /* Check if this provider matches */
111     if (IsEqualGUID(&Entry->ProviderId, &Context->ProviderId))
112     {
113         /* Get the information about the provider */
114         PathLen = wcslen(Entry->DllPath) + 1;
115         Context->FoundPathLen = PathLen;
116         Context->Found = 1;
117 
118         /* If we have enough room, copy path */
119         if (PathLen <= Context->ProviderDllPathLen)
120         {
121             wcscpy(Context->ProviderDllPath, Entry->DllPath);
122         }
123 
124         /* Stop enumeration */
125         return FALSE;
126     }
127     else
128     {
129         /* Continue enumeration */
130         return TRUE;
131     }
132 
133 }
134 
135 PTCATALOG
136 WSAAPI
OpenInitializedCatalog(VOID)137 OpenInitializedCatalog(VOID)
138 {
139     PTCATALOG Catalog;
140     HKEY WsKey;
141 
142     /* Allocate the catalog */
143     Catalog = WsTcAllocate();
144     if (Catalog)
145     {
146         /* Open the WS Key */
147         WsKey = WsOpenRegistryRoot();
148 
149         /* Initialize the catalog */
150         WsTcInitializeFromRegistry(Catalog, WsKey, NULL);
151 
152         /* Close the key */
153         RegCloseKey(WsKey);
154     }
155 
156     /* Return it */
157     return Catalog;
158 }
159 
160 /*
161  * @implemented
162  */
163 INT
164 WSPAPI
WSCEnumProtocols(IN LPINT lpiProtocols,OUT LPWSAPROTOCOL_INFOW lpProtocolBuffer,IN OUT LPDWORD lpdwBufferLength,OUT LPINT lpErrno)165 WSCEnumProtocols(IN LPINT lpiProtocols,
166                  OUT LPWSAPROTOCOL_INFOW lpProtocolBuffer,
167                  IN OUT LPDWORD lpdwBufferLength,
168                  OUT LPINT lpErrno)
169 {
170     INT Status;
171     PTCATALOG Catalog;
172     PROTOCOL_ENUM_CONTEXT Context;
173     DPRINT("WSCEnumProtocols: %p\n", lpiProtocols);
174 
175     /* Create a catalog object from the current one */
176     Catalog = OpenInitializedCatalog();
177     if (!Catalog)
178     {
179         /* Fail if we couldn't */
180         *lpErrno = WSAENOBUFS;
181         return SOCKET_ERROR;
182     }
183 
184     /* Setup the context */
185     Context.Protocols = lpiProtocols;
186     Context.ProtocolBuffer = lpProtocolBuffer;
187     Context.BufferLength = lpProtocolBuffer ? *lpdwBufferLength : 0;
188     Context.BufferUsed = 0;
189     Context.Count = 0;
190     Context.ErrorCode = ERROR_SUCCESS;
191 
192     /* Enumerate the catalog */
193     WsTcEnumerateCatalogItems(Catalog, ProtocolEnumerationProc, &Context);
194 
195     /* Get status */
196     Status = Context.Count;
197 
198     /* Check the error code */
199     if (Context.ErrorCode == ERROR_SUCCESS)
200     {
201         /* Check if enough space was available */
202         if (Context.BufferLength < Context.BufferUsed)
203         {
204             /* Fail and tell them how much we need */
205             *lpdwBufferLength = Context.BufferUsed;
206             *lpErrno = WSAENOBUFS;
207             Status = SOCKET_ERROR;
208         }
209     }
210     else
211     {
212         /* Failure, normalize error */
213         Status = SOCKET_ERROR;
214         *lpErrno = Context.ErrorCode;
215     }
216 
217     /* Delete the catalog object */
218     WsTcDelete(Catalog);
219 
220     /* Return */
221     return Status;
222 }
223 
224 /*
225  * @implemented
226  */
227 INT
228 WSAAPI
WSAEnumProtocolsA(IN LPINT lpiProtocols,OUT LPWSAPROTOCOL_INFOA lpProtocolBuffer,IN OUT LPDWORD lpdwBufferLength)229 WSAEnumProtocolsA(IN LPINT lpiProtocols,
230                   OUT LPWSAPROTOCOL_INFOA lpProtocolBuffer,
231                   IN OUT LPDWORD lpdwBufferLength)
232 {
233     INT error, i, count;
234     LPWSAPROTOCOL_INFOW protocolInfoW;
235     DWORD size;
236     DPRINT("WSAEnumProtocolsA: %p %p %p\n", lpiProtocols, lpProtocolBuffer, lpdwBufferLength);
237     if (!lpdwBufferLength)
238     {
239         SetLastError(WSAENOBUFS);
240         return SOCKET_ERROR;
241     }
242     count = WSCEnumProtocols(lpiProtocols, NULL, &size, &error);
243     if (!lpProtocolBuffer || *lpdwBufferLength < (size/sizeof(WSAPROTOCOL_INFOW))*sizeof(WSAPROTOCOL_INFOA))
244     {
245         *lpdwBufferLength = (size/sizeof(WSAPROTOCOL_INFOW))*sizeof(WSAPROTOCOL_INFOA);
246         SetLastError(WSAENOBUFS);
247         return SOCKET_ERROR;
248     }
249     protocolInfoW = HeapAlloc(WsSockHeap, 0, size);
250     count = WSCEnumProtocols(lpiProtocols, protocolInfoW, &size, &error);
251     if (SOCKET_ERROR == count)
252     {
253         HeapFree(WsSockHeap, 0, protocolInfoW);
254         SetLastError(error);
255         return SOCKET_ERROR;
256     }
257     *lpdwBufferLength = 0;
258     for (i = 0; i < count; i++)
259     {
260         /* Copy the data */
261         RtlMoveMemory(&lpProtocolBuffer[i],
262                       &protocolInfoW[i],
263                       sizeof(lpProtocolBuffer[0])-sizeof(lpProtocolBuffer[0].szProtocol));
264         wcstombs(lpProtocolBuffer[i].szProtocol, protocolInfoW[i].szProtocol, sizeof(lpProtocolBuffer[0].szProtocol));
265         *lpdwBufferLength += sizeof(WSAPROTOCOL_INFOA);
266     }
267     HeapFree(WsSockHeap, 0, protocolInfoW);
268     return i;
269 }
270 
271 /*
272  * @implemented
273  */
274 INT
275 WSAAPI
WSAEnumProtocolsW(IN LPINT lpiProtocols,OUT LPWSAPROTOCOL_INFOW lpProtocolBuffer,IN OUT LPDWORD lpdwBufferLength)276 WSAEnumProtocolsW(IN LPINT lpiProtocols,
277                   OUT LPWSAPROTOCOL_INFOW lpProtocolBuffer,
278                   IN OUT  LPDWORD lpdwBufferLength)
279 {
280     INT error, count;
281     DPRINT("WSAEnumProtocolsW: %p %p %p\n", lpiProtocols, lpProtocolBuffer, lpdwBufferLength);
282     count = WSCEnumProtocols(lpiProtocols, lpProtocolBuffer, lpdwBufferLength, &error);
283     if (SOCKET_ERROR == count)
284     {
285         SetLastError(error);
286         return SOCKET_ERROR;
287     }
288     return count;
289 }
290 
291 
292 /*
293  * @implemented
294  */
295 INT
296 WSPAPI
WPUGetProviderPath(IN LPGUID lpProviderId,OUT LPWSTR lpszProviderDllPath,IN OUT LPINT lpProviderDllPathLen,OUT LPINT lpErrno)297 WPUGetProviderPath(IN LPGUID lpProviderId,
298                    OUT LPWSTR lpszProviderDllPath,
299                    IN OUT LPINT lpProviderDllPathLen,
300                    OUT LPINT lpErrno)
301 {
302     return WSCGetProviderPath(lpProviderId, lpszProviderDllPath, lpProviderDllPathLen, lpErrno);
303 }
304 
305 /*
306  * @implemented
307  */
308 INT
309 WSAAPI
WSAProviderConfigChange(IN OUT LPHANDLE lpNotificationHandle,IN LPWSAOVERLAPPED lpOverlapped,IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)310 WSAProviderConfigChange(IN OUT LPHANDLE lpNotificationHandle,
311                         IN LPWSAOVERLAPPED lpOverlapped,
312                         IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
313 {
314     DPRINT("WSAProviderConfigChange: %p\n", lpNotificationHandle);
315     UNIMPLEMENTED;
316     SetLastError(WSAEINVAL);
317     return SOCKET_ERROR;
318 }
319 
320 /*
321  * @implemented
322  */
323 INT
324 WSPAPI
WSCGetProviderPath(IN LPGUID lpProviderId,OUT LPWSTR lpszProviderDllPath,IN OUT LPINT lpProviderDllPathLen,OUT LPINT lpErrno)325 WSCGetProviderPath(IN LPGUID lpProviderId,
326                    OUT LPWSTR lpszProviderDllPath,
327                    IN OUT LPINT lpProviderDllPathLen,
328                    OUT LPINT lpErrno)
329 {
330     PWSTHREAD Thread;
331     PWSPROCESS Process;
332     PNSCATALOG Catalog;
333     INT ErrorCode, PathLen;
334     PROVIDER_ENUM_CONTEXT Context;
335 
336     DPRINT("WSCGetProviderPath: %p %p %p %p\n", lpProviderId, lpszProviderDllPath, lpProviderDllPathLen, lpErrno);
337 
338     /* Enter prolog */
339     if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
340     {
341         /* FIXME: if WSANOTINITIALISED, we should init
342          * and perform the search!
343          */
344 
345         /* Leave now */
346         *lpErrno = ErrorCode;
347         return SOCKET_ERROR;
348     }
349 
350     /* Get the catalog */
351     Catalog = WsProcGetNsCatalog(Process);
352 
353     _SEH2_TRY
354     {
355         /* Setup the context */
356         Context.ProviderId = *lpProviderId;
357         Context.ProviderDllPath = lpszProviderDllPath;
358         Context.ProviderDllPathLen = *lpProviderDllPathLen;
359         Context.FoundPathLen = 0;
360         Context.Found = 0;
361         Context.ErrorCode = ERROR_SUCCESS;
362 
363         ErrorCode = ERROR_SUCCESS;
364 
365         /* Enumerate the catalog */
366         WsNcEnumerateCatalogItems(Catalog, ProviderEnumerationProc, &Context);
367 
368         /* Check the error code */
369         if (Context.ErrorCode == ERROR_SUCCESS)
370         {
371             /* Check if provider was found */
372             if (Context.Found)
373             {
374                 PathLen = Context.FoundPathLen;
375 
376                 /* Check whether buffer is too small
377                  * If it isn't, return length without null char
378                  * (see ProviderEnumerationProc)
379                  */
380                 if (Context.FoundPathLen <= *lpProviderDllPathLen)
381                 {
382                     PathLen = Context.FoundPathLen - 1;
383                 }
384                 else
385                 {
386                     ErrorCode = WSAEFAULT;
387                 }
388 
389                 /* Set returned/required length */
390                 *lpProviderDllPathLen = PathLen;
391             }
392             else
393             {
394                 ErrorCode = WSAEINVAL;
395             }
396         }
397         else
398         {
399             ErrorCode = Context.ErrorCode;
400         }
401     }
402     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
403     {
404         ErrorCode = WSAEFAULT;
405     }
406     _SEH2_END;
407 
408     /* Do we have to return failure? */
409     if (ErrorCode != ERROR_SUCCESS)
410     {
411         *lpErrno = ErrorCode;
412         return SOCKET_ERROR;
413     }
414 
415     return 0;
416 }
417