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