ReactOS 0.4.17-dev-1321-g5c122a9
nsquery.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS WinSock 2 API
4 * FILE: dll/win32/ws2_32/src/nsquery.c
5 * PURPOSE: Namespace Query Object
6 * PROGRAMMER: Alex Ionescu (alex@relsoft.net)
7 */
8
9/* INCLUDES ******************************************************************/
10
11#include <ws2_32.h>
12
13/* DATA **********************************************************************/
14
15#define WsNqLock() EnterCriticalSection(&NsQuery->Lock)
16#define WsNqUnlock() LeaveCriticalSection(&NsQuery->Lock)
17
18/* FUNCTIONS *****************************************************************/
19
23{
24 PNSQUERY NsQuery;
25
26 /* Allocate the object */
27 NsQuery = HeapAlloc(WsSockHeap, HEAP_ZERO_MEMORY, sizeof(*NsQuery));
28 if (NsQuery)
29 {
30 /* Set non-zero fields */
31 NsQuery->Signature = ~0xBEADFACE;
33 NsQuery->TryAgain = TRUE;
34 }
35
36 /* Return it */
37 return NsQuery;
38}
39
43{
44 /* Initialize the lock */
46
47 /* Set initial reference count and signature */
48 Query->RefCount = 1;
49 Query->Signature = 0xBEADFACE;
50
51 /* Return success */
52 return ERROR_SUCCESS;
53}
54
55BOOL
58{
59 /* Check the signature first */
60 if (Query->Signature != 0xBEADFACE) return FALSE;
61
62 /* Validate the reference count */
63 if (!Query->RefCount) return FALSE;
64
65 /* Increase reference count */
66 InterlockedIncrement(&Query->RefCount);
67
68 /* Return success */
69 return TRUE;
70}
71
72VOID
75{
78
79 /* Make sure that we got initialized */
80 if (!NsQuery->ProviderList.Flink) return;
81
82 /* Loop the provider list */
83 while (!IsListEmpty(&NsQuery->ProviderList))
84 {
85 /* Remove the entry */
86 Entry = RemoveHeadList(&NsQuery->ProviderList);
87
88 /* Get the provider */
90
91 /* Delete it */
93 }
94
95 /* Remove the signature and delete the lock */
96 NsQuery->Signature = ~0xBEADFACE;
97 DeleteCriticalSection(&NsQuery->Lock);
98
99 /* Free us */
100 HeapFree(WsSockHeap, 0, NsQuery);
101}
102
103VOID
104WSAAPI
106{
107 /* Decrease the reference count and check if it's zero */
108 if (!InterlockedDecrement(&Query->RefCount))
109 {
110 /* Delete us*/
112 }
113}
114
115BOOL
116WSAAPI
119{
121 BOOLEAN GoOn = TRUE;
122 PENUM_CONTEXT EnumContext = (PENUM_CONTEXT)Context;
123 PNSQUERY NsQuery = EnumContext->NsQuery;
124 DWORD NamespaceId = Entry->NamespaceId;
125
126 /* Match the namespace ID, protocols and make sure it's enabled */
127 if ((((EnumContext->lpqsRestrictions->dwNameSpace == NamespaceId) ||
128 (EnumContext->lpqsRestrictions->dwNameSpace == NS_ALL)) &&
129 (!(EnumContext->lpqsRestrictions->dwNumberOfProtocols) ||
130 (WsNcMatchProtocols(NamespaceId,
131 Entry->AddressFamily,
132 EnumContext->lpqsRestrictions)))) &&
133 (Entry->Enabled))
134 {
135 /* Get the provider */
136 if (!(Provider = Entry->Provider))
137 {
138 /* None was loaded, load it */
139 if (WsNcLoadProvider(EnumContext->Catalog, Entry) != ERROR_SUCCESS)
140 {
141 /* Return TRUE to continue enumerating */
142 return TRUE;
143 }
144
145 /* Set the provider */
146 Provider = Entry->Provider;
147 }
148
149 /* Add it to the query */
150 if (!WsNqAddProvider(NsQuery, Provider))
151 {
152 /* We failed */
153 EnumContext->ErrorCode = WSASYSCALLFAILURE;
154 GoOn = FALSE;
155 }
156 }
157
158 /* Return to caller */
159 return GoOn;
160}
161
162DWORD
163WSAAPI
165{
168
169 /* Protect us from closure */
170 WsNqLock();
171 NsQuery->ShuttingDown = TRUE;
172
173 /* Get the list and loop */
174 Entry = NsQuery->ProviderList.Flink;
175 while (Entry != &NsQuery->ProviderList)
176 {
177 /* Get the provider */
179
180 /* Call its routine */
182
183 /* Move to the next one */
184 Entry = Entry->Flink;
185 }
186
187 /* Release lock and return success */
188 WsNqUnlock();
189 return ERROR_SUCCESS;
190}
191
192DWORD
193WSAAPI
195 IN DWORD ControlFlags,
198{
199 INT ErrorCode = SOCKET_ERROR, OldErrorCode;
200 PNSQUERY_PROVIDER Provider, NextProvider;
202
203 /* Make sure we're not shutting down */
204 if (NsQuery->ShuttingDown)
205 {
206 /* We are shutting down, fail */
208 return ErrorCode;
209 }
210
211 /* Acquire query lock */
212 WsNqLock();
213
214 /* Check if we already have an active provider */
215 NextProvider = NsQuery->ActiveProvider;
216 if (!NextProvider)
217 {
218 /* Make sure we have a current provider */
219 if (!NsQuery->CurrentProvider)
220 {
221 /* We don't; fail */
222 WsNqUnlock();
224 return SOCKET_ERROR;
225 }
226
227 /* Get the last provider in the list and start looping */
228 Entry = NsQuery->ProviderList.Blink;
229 NextProvider = CONTAINING_RECORD(Entry, NSQUERY_PROVIDER, QueryLink);
230 while (NextProvider)
231 {
232 /* Check if this is a new-style provider */
233 if (NextProvider->Provider->Service.NSPIoctl)
234 {
235 /* Remove it and re-add it on top */
236 RemoveEntryList(&NextProvider->QueryLink);
237 InsertHeadList(&NsQuery->ProviderList, &NextProvider->QueryLink);
238
239 /* Set it as the active provider and exit the loop */
240 NsQuery->ActiveProvider = NextProvider;
241 break;
242 }
243
244 /* Get the previous provider */
245 NextProvider = WsNqPreviousProvider(NsQuery, NextProvider);
246 }
247 }
248
249 /* Release the lock */
250 WsNqUnlock();
251
252 /* Restart and keep looping as long as there is an active provider */
253 while (NextProvider)
254 {
255 /* Call its routine */
257 ControlFlags,
259 Results);
260 /* Check for error or shutdown */
261 if ((ErrorCode == ERROR_SUCCESS) ||
262 (GetLastError() == WSAEFAULT) || (NsQuery->ShuttingDown))
263 {
264 /* Get out */
265 break;
266 }
267
268 /* Acquire Query Lock */
269 WsNqLock();
270
271 /* Check if we have an active provider */
272 if (NsQuery->ActiveProvider)
273 {
274 /* Save the old provider and get the next one */
275 Provider = NextProvider;
276 NextProvider = WsNqNextProvider(NsQuery, NsQuery->ActiveProvider);
277
278 /* Was the old provider our active? */
279 if (Provider == NsQuery->ActiveProvider)
280 {
281 /* Change our active provider to the new one */
282 NsQuery->ActiveProvider = NextProvider;
283 }
284 }
285 else
286 {
287 /* No next provider */
288 NextProvider = NULL;
289 }
290
291 /* Check if we failed and if we can try again */
292 if (!(NextProvider) &&
293 (ErrorCode == SOCKET_ERROR) &&
294 (NsQuery->TryAgain))
295 {
296 /* Save the error code so RAS doesn't overwrite it */
297 OldErrorCode = GetLastError();
298
299 /* Make sure we won't try for a 3rd time */
300 NsQuery->TryAgain = FALSE;
301
302 /* Call the helper to auto-dial */
303 if (WSAttemptAutodialName(NsQuery->QuerySet))
304 {
305 /* It succeeded, so we'll delete the current state. */
306 while (!IsListEmpty(&NsQuery->ProviderList))
307 {
308 /* Remove the entry and get its provider */
309 Entry = RemoveHeadList(&NsQuery->ProviderList);
312 QueryLink);
313
314 /* Reset it */
317 }
318
319 /* Start a new query */
320 if (WsNqLookupServiceBegin(NsQuery,
321 NsQuery->QuerySet,
322 NsQuery->ControlFlags,
323 NsQuery->Catalog) == ERROR_SUCCESS)
324 {
325 /* New query succeeded, set active provider now */
326 NsQuery->ActiveProvider =
327 WsNqNextProvider(NsQuery, NsQuery->ActiveProvider);
328 }
329 }
330 else
331 {
332 /* Reset the error code */
333 SetLastError(OldErrorCode);
334 }
335 }
336
337 /* Release lock */
338 WsNqUnlock();
339 }
340
341 /* Return */
342 return ErrorCode;
343}
344
345DWORD
346WSAAPI
348 IN LPWSAQUERYSETW Restrictions,
349 IN DWORD ControlFlags,
350 IN PNSCATALOG Catalog)
351{
352 WSASERVICECLASSINFOW ClassInfo;
353 LPWSASERVICECLASSINFOW pClassInfo = &ClassInfo;
354 PNSQUERY_PROVIDER Provider, NextProvider;
357 DWORD ClassInfoSize;
358 PNSCATALOG_ENTRY CatalogEntry = NULL;
359 ENUM_CONTEXT EnumContext;
360 BOOLEAN TryAgain;
361
362 /* Check for RAS Auto-dial attempt */
363 if (NsQuery->TryAgain)
364 {
365 /* Make a copy of the query set */
366 ErrorCode = CopyQuerySetW(Restrictions, &NsQuery->QuerySet);
367 TryAgain = (ErrorCode == ERROR_SUCCESS);
368
369 /* Check if we'll try again */
370 if (!TryAgain)
371 {
372 /* We won't, fail */
375 NsQuery->TryAgain = FALSE;
376 goto Exit;
377 }
378
379 /* Cache the information for a restart */
380 NsQuery->ControlFlags = ControlFlags;
381 NsQuery->Catalog = Catalog;
382 }
383
384 /* Check if we have a specific ID */
385 if (Restrictions->lpNSProviderId)
386 {
387 /* Get the catalog entry */
389 Restrictions->lpNSProviderId,
390 &CatalogEntry);
391 /* Check for failure */
393 {
394 /* Fail */
397 goto Exit;
398 }
399 /* We succeeded, add this provider */
400 else if (!WsNqAddProvider(NsQuery, CatalogEntry->Provider))
401 {
402 /* Fail */
405 goto Exit;
406 }
407 }
408 else
409 {
410 /* Setup the lookup context */
411 EnumContext.lpqsRestrictions = Restrictions;
412 EnumContext.ErrorCode = ERROR_SUCCESS;
413 EnumContext.NsQuery = NsQuery;
414 EnumContext.Catalog = Catalog;
415
416 /* Do a lookup for every entry */
419 &EnumContext);
420 ErrorCode = EnumContext.ErrorCode;
421
422 /* Check for success */
424 {
425 /* Fail */
428 goto Exit;
429 }
430 }
431
432 /* Get the class information */
433 ClassInfo.lpServiceClassId = Restrictions->lpServiceClassId;
434 ErrorCode = WsNcGetServiceClassInfo(Catalog, &ClassInfoSize, pClassInfo);
435
436 /* Check if more buffer space is needed */
437 if ((ErrorCode == SOCKET_ERROR) && (GetLastError() == WSAEFAULT))
438 {
439 /* FIXME: The WS 2.2 spec hasn't been finalized yet on this... */
440 }
441 else
442 {
443 /* Assume success */
445 }
446
447 /* Check if the provider list is empty */
448 if (IsListEmpty(&NsQuery->ProviderList))
449 {
450 /* We don't have any providers to handle this! */
453 goto Exit;
454 }
455
456 /* Get the first provider and loop */
457 Entry = NsQuery->ProviderList.Flink;
458 NextProvider = CONTAINING_RECORD(Entry, NSQUERY_PROVIDER, QueryLink);
459 while (NextProvider)
460 {
461 /* Call it */
463 Restrictions,
464 pClassInfo,
465 ControlFlags);
466 /* Check for error */
467 if (ErrorCode == SOCKET_ERROR)
468 {
469 /* Remove this provider, get the next one, delete the old one */
470 Provider = NextProvider;
471 NextProvider = WsNqNextProvider(NsQuery, NextProvider);
472 RemoveEntryList(&Provider->QueryLink);
474 }
475 else
476 {
477 /* Get the next provider */
478 NextProvider = WsNqNextProvider(NsQuery, NextProvider);
479 }
480 }
481
482Exit:
483 /* Check if we had an error somewhere */
484 if (ErrorCode == SOCKET_ERROR)
485 {
486 /* Loop the list */
487 while (!IsListEmpty(&NsQuery->ProviderList))
488 {
489 /* Remove this provider */
490 Entry = RemoveHeadList(&NsQuery->ProviderList);
491
492 /* Get the failed provider and delete it */
495 }
496 }
497 else
498 {
499 /* Set the active provider */
500 Entry = NsQuery->ProviderList.Flink;
501 NsQuery->ActiveProvider = CONTAINING_RECORD(Entry,
503 QueryLink);
504 }
505
506 /* Return */
507 return ErrorCode;
508}
509
511WSAAPI
514{
515 PNSQUERY_PROVIDER NextProvider = NULL;
517
518 /* Get the first entry and get its provider */
519 Entry = Provider->QueryLink.Flink;
520 if (Entry != &Query->ProviderList)
521 {
522 /* Get the current provider */
523 NextProvider = CONTAINING_RECORD(Entry, NSQUERY_PROVIDER, QueryLink);
524 }
525
526 /* Return it */
527 return NextProvider;
528}
529
531WSAAPI
534{
535 PNSQUERY_PROVIDER PrevProvider = NULL;
537
538 /* Get the last entry and get its provider */
539 Entry = Provider->QueryLink.Blink;
540 if (Entry != &Query->ProviderList)
541 {
542 /* Get the current provider */
543 PrevProvider = CONTAINING_RECORD(Entry, NSQUERY_PROVIDER, QueryLink);
544 }
545
546 /* Return it */
547 return PrevProvider;
548}
549
550BOOL
551WSAAPI
554{
555 BOOL Success = TRUE;
556 PNSQUERY_PROVIDER QueryProvider;
557
558 /* Allocate a new Query Provider */
559 if ((QueryProvider = WsNqProvAllocate()))
560 {
561 /* Initialize it */
562 WsNqProvInitialize(QueryProvider, Provider);
563
564 /* Insert it into the provider list */
565 InsertTailList(&Query->ProviderList, &QueryProvider->QueryLink);
566 }
567 else
568 {
569 /* We failed */
571 Success = FALSE;
572 }
573
574 /* Return */
575 return Success;
576}
577
unsigned char BOOLEAN
Definition: actypes.h:127
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define ERROR_SUCCESS
Definition: deptool.c:10
PLIST_ENTRY Entry
Definition: devhcd.cpp:1262
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define SetLastError(x)
Definition: compat.h:752
#define HeapAlloc
Definition: compat.h:733
#define HeapFree(x, y, z)
Definition: compat.h:735
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define InsertHeadList(ListHead, Entry)
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
@ Success
Definition: eventcreate.c:712
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
_In_ const GUID _In_ ULONG _In_opt_ PFN_WDF_WMI_INSTANCE_QUERY_INSTANCE Query
Definition: hubwmi.cpp:114
_In_ PIRP _In_ PIO_COMPLETION_ROUTINE _In_ PVOID Context
Definition: kse.h:81
macro TEXTAREA section xr p2align endm macro DATAAREA section dw endm macro RODATAAREA section dr endm macro EXPORT Attribute global Name endm macro IMPORT Target ifc WEAK weak Name set Target endif endm set macro SET_COMDAT_ALIGNMENT Alignment set Alignment endm macro NESTED_ENTRY Name global Name p2align xr p2align __ComdatAlignment NESTED_ENTRY Name endm macro ALTERNATE_ENTRY Name global Name Results
Definition: kxarm64.h:154
struct _ENUM_CONTEXT * PENUM_CONTEXT
_In_ NDIS_ERROR_CODE ErrorCode
Definition: ndis.h:4438
#define NS_ALL
Definition: nspapi.h:8
DWORD WSAAPI WsNqLookupServiceEnd(IN PNSQUERY NsQuery)
Definition: nsquery.c:164
PNSQUERY_PROVIDER WSAAPI WsNqNextProvider(IN PNSQUERY Query, IN PNSQUERY_PROVIDER Provider)
Definition: nsquery.c:512
DWORD WSAAPI WsNqLookupServiceNext(IN PNSQUERY NsQuery, IN DWORD ControlFlags, OUT PDWORD BufferLength, OUT LPWSAQUERYSETW Results)
Definition: nsquery.c:194
VOID WSAAPI WsNqDelete(IN PNSQUERY NsQuery)
Definition: nsquery.c:74
BOOL WSAAPI WsNqValidateAndReference(IN PNSQUERY Query)
Definition: nsquery.c:57
BOOL WSAAPI WsNqBeginEnumerationProc(PVOID Context, PNSCATALOG_ENTRY Entry)
Definition: nsquery.c:117
#define WsNqUnlock()
Definition: nsquery.c:16
PNSQUERY WSAAPI WsNqAllocate(VOID)
Definition: nsquery.c:22
#define WsNqLock()
Definition: nsquery.c:15
VOID WSAAPI WsNqDereference(IN PNSQUERY Query)
Definition: nsquery.c:105
DWORD WSAAPI WsNqLookupServiceBegin(IN PNSQUERY NsQuery, IN LPWSAQUERYSETW Restrictions, IN DWORD ControlFlags, IN PNSCATALOG Catalog)
Definition: nsquery.c:347
DWORD WSAAPI WsNqInitialize(IN PNSQUERY Query)
Definition: nsquery.c:42
BOOL WSAAPI WsNqAddProvider(IN PNSQUERY Query, IN PNS_PROVIDER Provider)
Definition: nsquery.c:552
PNSQUERY_PROVIDER WSAAPI WsNqPreviousProvider(IN PNSQUERY Query, IN PNSQUERY_PROVIDER Provider)
Definition: nsquery.c:532
DWORD * PDWORD
Definition: pedump.c:68
BOOL WINAPI WSAttemptAutodialName(IN CONST LPWSAQUERYSETW Restrictions)
Definition: winsock.c:58
static void Exit(void)
Definition: sock.c:1330
static LPWSAQUERYSETW
Definition: sock.c:90
PNSCATALOG Catalog
Definition: ws2_32p.h:211
PNSQUERY NsQuery
Definition: ws2_32p.h:210
INT ErrorCode
Definition: ws2_32p.h:209
LPWSAQUERYSETW lpqsRestrictions
Definition: ws2_32p.h:208
Definition: typedefs.h:120
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
Definition: ws2_32p.h:122
PNS_PROVIDER Provider
Definition: ws2_32p.h:125
NSP_ROUTINE Service
Definition: ws2_32p.h:111
LPNSPIOCTL NSPIoctl
Definition: ws2spi.h:665
LIST_ENTRY QueryLink
Definition: ws2_32p.h:116
PNS_PROVIDER Provider
Definition: ws2_32p.h:117
LIST_ENTRY ProviderList
Definition: ws2_32p.h:150
DWORD Signature
Definition: ws2_32p.h:147
DWORD TryAgain
Definition: ws2_32p.h:157
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:687
int32_t INT
Definition: typedefs.h:58
#define IN
Definition: typedefs.h:39
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
#define OUT
Definition: typedefs.h:40
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG BufferLength
Definition: wdfdevice.h:3777
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)
#define WSAECANCELLED
Definition: winerror.h:2897
#define WSASYSCALLFAILURE
Definition: winerror.h:2901
#define WSAEINVAL
Definition: winerror.h:2845
#define WSASERVICE_NOT_FOUND
Definition: winerror.h:2902
#define WSAEFAULT
Definition: winerror.h:2844
#define WSA_E_NO_MORE
Definition: winerror.h:2904
#define WSA_NOT_ENOUGH_MEMORY
Definition: winsock2.h:614
#define WSAAPI
Definition: winsock2.h:599
#define SOCKET_ERROR
Definition: winsock.h:327
BOOL WSAAPI WsNcMatchProtocols(IN DWORD NameSpace, IN LONG AddressFamily, IN LPWSAQUERYSETW QuerySet)
Definition: nscatalo.c:561
INT WSAAPI WsNcGetCatalogFromProviderId(IN PNSCATALOG Catalog, IN LPGUID ProviderId, OUT PNSCATALOG_ENTRY *CatalogEntry)
Definition: nscatalo.c:517
INT WSAAPI WsNcLoadProvider(IN PNSCATALOG Catalog, IN PNSCATALOG_ENTRY CatalogEntry)
Definition: nscatalo.c:400
PNSQUERY_PROVIDER WSAAPI WsNqProvAllocate(VOID)
Definition: nsprovid.c:17
INT WSAAPI CopyQuerySetW(IN LPWSAQUERYSETW UnicodeSet, OUT LPWSAQUERYSETW *UnicodeCopy)
Definition: qshelpr.c:1050
INT WSAAPI WsNcGetServiceClassInfo(IN PNSCATALOG Catalog, IN OUT LPDWORD BugSize, IN OUT LPWSASERVICECLASSINFOW lpServiceClassInfo)
Definition: nscatalo.c:444
DWORD WSAAPI WsNqProvLookupServiceEnd(IN PNSQUERY_PROVIDER QueryProvider)
Definition: nsprovid.c:192
DWORD WSAAPI WsNqProvInitialize(IN PNSQUERY_PROVIDER QueryProvider, IN PNS_PROVIDER Provider)
Definition: nsprovid.c:30
VOID WSAAPI WsNcEnumerateCatalogItems(IN PNSCATALOG Catalog, IN PNSCATALOG_ENUMERATE_PROC Callback, IN PVOID Context)
Definition: nscatalo.c:371
DWORD WSAAPI WsNqProvLookupServiceBegin(IN PNSQUERY_PROVIDER QueryProvider, IN LPWSAQUERYSETW QuerySet, IN LPWSASERVICECLASSINFOW ServiceClassInfo, IN DWORD)
Definition: nsprovid.c:216
HANDLE WsSockHeap
Definition: dllmain.c:21
DWORD WSAAPI WsNqProvLookupServiceNext(IN PNSQUERY_PROVIDER QueryProvider, DWORD, PDWORD, LPWSAQUERYSETW QuerySet)
VOID WSAAPI WsNqProvDelete(IN PNSQUERY_PROVIDER QueryProvider)
Definition: nsprovid.c:45