2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS WinSock 2 API
4 * FILE: dll/win32/ws2_32_new/src/nsquery.c
5 * PURPOSE: Namespace Query Object
6 * PROGRAMMER: Alex Ionescu (alex@relsoft.net)
9 /* INCLUDES ******************************************************************/
13 /* DATA **********************************************************************/
15 #define WsNqLock() EnterCriticalSection((LPCRITICAL_SECTION)&NsQuery->Lock);
16 #define WsNqUnlock() LeaveCriticalSection((LPCRITICAL_SECTION)&NsQuery->Lock);
18 /* FUNCTIONS *****************************************************************/
26 /* Allocate the object */
27 NsQuery
= HeapAlloc(WsSockHeap
, HEAP_ZERO_MEMORY
, sizeof(*NsQuery
));
29 /* Set non-zero fields */
30 NsQuery
->Signature
= ~0xBEADFACE;
31 InitializeListHead(&NsQuery
->ProviderList
);
32 NsQuery
->TryAgain
= TRUE
;
40 WsNqInitialize(IN PNSQUERY Query
)
42 /* Initialize the lock */
43 InitializeCriticalSection((LPCRITICAL_SECTION
)&Query
->Lock
);
45 /* Set initial reference count and signature */
47 Query
->Signature
= 0xBEADFACE;
55 WsNqValidateAndReference(IN PNSQUERY Query
)
57 /* Check the signature first */
58 if (Query
->Signature
!= 0xBEADFACE) return FALSE
;
60 /* Validate the reference count */
61 if (!Query
->RefCount
) return FALSE
;
63 /* Increase reference count */
64 InterlockedIncrement(&Query
->RefCount
);
72 WsNqDelete(IN PNSQUERY NsQuery
)
74 PNSQUERY_PROVIDER Provider
;
77 /* Make sure that we got initialized */
78 if (!NsQuery
->ProviderList
.Flink
) return;
80 /* Loop the provider list */
81 while (!IsListEmpty(&NsQuery
->ProviderList
))
83 /* Remove the entry */
84 Entry
= RemoveHeadList(&NsQuery
->ProviderList
);
86 /* Get the provider */
87 Provider
= CONTAINING_RECORD(Entry
, NSQUERY_PROVIDER
, QueryLink
);
90 WsNqProvDelete(Provider
);
93 /* Remove the signature and delete the lock */
94 NsQuery
->Signature
= ~0xBEADFACE;
95 DeleteCriticalSection((LPCRITICAL_SECTION
)&NsQuery
->Lock
);
98 HeapFree(WsSockHeap
, 0, NsQuery
);
103 WsNqDereference(IN PNSQUERY Query
)
105 /* Decrease the reference count and check if it's zero */
106 if (!InterlockedDecrement(&Query
->RefCount
))
115 WsNqBeginEnumerationProc(PVOID Context
,
116 PNSCATALOG_ENTRY Entry
)
118 PNS_PROVIDER Provider
;
120 PENUM_CONTEXT EnumContext
= (PENUM_CONTEXT
)Context
;
121 PNSQUERY NsQuery
= EnumContext
->NsQuery
;
122 DWORD NamespaceId
= Entry
->NamespaceId
;
124 /* Match the namespace ID, protocols and make sure it's enabled */
125 if ((((EnumContext
->lpqsRestrictions
->dwNameSpace
== NamespaceId
) ||
126 (EnumContext
->lpqsRestrictions
->dwNameSpace
== NS_ALL
)) &&
127 (!(EnumContext
->lpqsRestrictions
->dwNumberOfProtocols
) ||
128 (WsNcMatchProtocols(NamespaceId
,
129 Entry
->AddressFamily
,
130 EnumContext
->lpqsRestrictions
)))) &&
133 /* Get the provider */
134 if (!(Provider
= Entry
->Provider
))
136 /* None was laoded, load it */
137 if ((WsNcLoadProvider(EnumContext
->Catalog
, Entry
) != ERROR_SUCCESS
))
139 /* return fake success */
143 /* Set the provider */
144 Provider
= Entry
->Provider
;
147 /* Add it to the query */
148 if (!(WsNqAddProvider(NsQuery
, Provider
)))
151 EnumContext
->ErrorCode
= WSASYSCALLFAILURE
;
156 /* Return to caller */
162 WsNqLookupServiceEnd(IN PNSQUERY NsQuery
)
164 PNSQUERY_PROVIDER Provider
;
167 /* Protect us from closure */
169 NsQuery
->ShuttingDown
= TRUE
;
171 /* Get the list and loop */
172 Entry
= NsQuery
->ProviderList
.Flink
;
173 while (Entry
!= &NsQuery
->ProviderList
)
175 /* Get the provider */
176 Provider
= CONTAINING_RECORD(Entry
, NSQUERY_PROVIDER
, QueryLink
);
178 /* Call its routine */
179 WsNqProvLookupServiceEnd(Provider
);
181 /* Move to the next one */
182 Entry
= Entry
->Flink
;
185 /* Release lock and return success */
187 return ERROR_SUCCESS
;
192 WsNqLookupServiceNext(IN PNSQUERY NsQuery
,
193 IN DWORD ControlFlags
,
194 OUT PDWORD BufferLength
,
195 OUT LPWSAQUERYSETW Results
)
197 PNSQUERY_PROVIDER Provider
, NextProvider
;
198 INT ErrorCode
= SOCKET_ERROR
, OldErrorCode
;
201 /* Make sure we're not shutting down */
202 if (!NsQuery
->ShuttingDown
)
204 /* Acquire query lock */
207 /* Check if we already have an active provider */
208 NextProvider
= NsQuery
->ActiveProvider
;
211 /* Make sure we have a current provider */
212 if (!NsQuery
->CurrentProvider
)
216 SetLastError(WSA_E_NO_MORE
);
220 /* Get the first provider on the list and start looping */
221 Entry
= NsQuery
->ProviderList
.Blink
;
222 NextProvider
= CONTAINING_RECORD(Entry
, NSQUERY_PROVIDER
, QueryLink
);
225 /* Check if this is a new-style provider */
226 if (NextProvider
->Provider
->Service
.NSPIoctl
)
228 /* Remove it and re-add it on top */
229 RemoveEntryList(&NextProvider
->QueryLink
);
230 InsertHeadList(&NsQuery
->ProviderList
, &NextProvider
->QueryLink
);
232 /* Set it as the active provider and exit the loop */
233 NsQuery
->ActiveProvider
= NextProvider
;
237 /* Get the previous provider */
238 NextProvider
= WsNqPreviousProvider(NsQuery
, NextProvider
);
242 /* Release the lock */
245 /* Check if we have an active provider now */
251 /* Call its routine */
252 ErrorCode
= WsNqProvLookupServiceNext(NextProvider
,
256 /* Check for error or shutdown */
257 if ((ErrorCode
== ERROR_SUCCESS
) ||
258 (GetLastError() == WSAEFAULT
) || (NsQuery
->ShuttingDown
))
264 /* Acquire Query Lock */
267 /* Save the current active provider */
268 Provider
= NsQuery
->ActiveProvider
;
270 /* Check if one exists */
273 /* Get the next one */
274 NextProvider
= WsNqNextProvider(NsQuery
,
275 NsQuery
->ActiveProvider
);
277 /* Was the old provider our active? */
278 if (Provider
== NsQuery
->ActiveProvider
)
280 /* Change our active provider to the new one */
281 NsQuery
->ActiveProvider
= NextProvider
;
286 /* No next provider */
290 /* Check if we failed and if we can try again */
291 if (!(NextProvider
) &&
292 (ErrorCode
== SOCKET_ERROR
) &&
295 /* Save the error code so RAS doesn't overwrite it */
296 OldErrorCode
= GetLastError();
298 /* Make sure we won't try for a 3rd time */
299 NsQuery
->TryAgain
= FALSE
;
301 /* Call the helper to auto-dial */
302 if (WSAttemptAutodialName(NsQuery
->QuerySet
))
304 /* It suceeded, so we'll delete the current state. */
305 while (!IsListEmpty(&NsQuery
->ProviderList
))
307 /* Remove the entry and get its provider */
308 Entry
= RemoveHeadList(&NsQuery
->ProviderList
);
309 Provider
= CONTAINING_RECORD(Entry
,
314 WsNqProvLookupServiceEnd(Provider
);
315 WsNqProvDelete(Provider
);
318 /* Start a new query */
319 if (!WsNqLookupServiceBegin(NsQuery
,
321 NsQuery
->ControlFlags
,
324 /* New query succeeded, set active provider now */
325 NsQuery
->ActiveProvider
=
326 WsNqNextProvider(NsQuery
,
327 NsQuery
->ActiveProvider
);
332 /* Reset the error code */
333 SetLastError(OldErrorCode
);
340 /* Keep looping as long as there is a provider */
341 } while (NextProvider
);
346 /* We are shuting down; fail */
347 SetLastError(WSAECANCELLED
);
356 WsNqLookupServiceBegin(IN PNSQUERY NsQuery
,
357 IN LPWSAQUERYSETW Restrictions
,
358 IN DWORD ControlFlags
,
359 IN PNSCATALOG Catalog
)
361 WSASERVICECLASSINFOW ClassInfo
;
362 PNSQUERY_PROVIDER Provider
;
363 LPWSASERVICECLASSINFOW pClassInfo
= NULL
;
364 PNSQUERY_PROVIDER NextProvider
;
368 PNSCATALOG_ENTRY CatalogEntry
;
369 ENUM_CONTEXT EnumContext
;
372 /* Check for RAS Auto-dial attempt */
373 if (NsQuery
->TryAgain
)
375 /* Make a copy of the query set */
376 ErrorCode
= CopyQuerySetW(Restrictions
, &NsQuery
->QuerySet
);
377 TryAgain
= (ErrorCode
== ERROR_SUCCESS
);
379 /* Check if we'll try again */
383 SetLastError(ErrorCode
);
384 ErrorCode
= SOCKET_ERROR
;
385 NsQuery
->TryAgain
= FALSE
;
389 /* Cache the information for a restart */
390 NsQuery
->ControlFlags
= ControlFlags
;
391 NsQuery
->Catalog
= Catalog
;
394 /* Check if we have a specific ID */
395 if (Restrictions
->lpNSProviderId
)
397 /* Get the provider */
398 ErrorCode
= WsNcGetCatalogFromProviderId(Catalog
,
399 Restrictions
->lpNSProviderId
,
401 /* Check for success */
402 if (ErrorCode
!= ERROR_SUCCESS
)
405 SetLastError(WSAEINVAL
);
406 ErrorCode
= SOCKET_ERROR
;
411 /* Add this provider */
412 WsNqAddProvider(NsQuery
, CatalogEntry
->Provider
);
417 /* Setup the lookup context */
418 EnumContext
.lpqsRestrictions
= Restrictions
;
419 EnumContext
.ErrorCode
= ERROR_SUCCESS
;
420 EnumContext
.NsQuery
= NsQuery
;
421 EnumContext
.Catalog
= Catalog
;
423 /* Do a lookup for every entry */
424 WsNcEnumerateCatalogItems(Catalog
,
425 WsNqBeginEnumerationProc
,
427 ErrorCode
= EnumContext
.ErrorCode
;
429 /* Check for success */
430 if (ErrorCode
!= ERROR_SUCCESS
)
433 SetLastError(WSAEINVAL
);
434 ErrorCode
= SOCKET_ERROR
;
439 /* Get the class information */
440 ClassInfo
.lpServiceClassId
= Restrictions
->lpServiceClassId
;
441 ErrorCode
= WsNcGetServiceClassInfo(Catalog
, &ClassInfoSize
, &ClassInfo
);
443 /* Check if more buffer space is needed */
444 if ((ErrorCode
== SOCKET_ERROR
) && (GetLastError() == WSAEFAULT
))
446 /* FIXME: The WS 2.2 spec hasn't been finalized yet on this... */
451 ErrorCode
= ERROR_SUCCESS
;
454 /* Check if the provider list is empty */
455 if (IsListEmpty(&NsQuery
->ProviderList
))
457 /* We don't have any providers to handle this! */
458 ErrorCode
= SOCKET_ERROR
;
459 SetLastError(WSASERVICE_NOT_FOUND
);
463 /* Get the first provider and loop */
464 Entry
= NsQuery
->ProviderList
.Flink
;
465 NextProvider
= CONTAINING_RECORD(Entry
, NSQUERY_PROVIDER
, QueryLink
);
469 ErrorCode
= WsNqProvLookupServiceBegin(NextProvider
,
473 /* Check for error */
474 if (ErrorCode
== SOCKET_ERROR
)
476 /* Remove this provider, get the next one, delete the old one */
477 Provider
= NextProvider
;
478 NextProvider
= WsNqNextProvider(NsQuery
, NextProvider
);
479 RemoveEntryList(&Provider
->QueryLink
);
480 WsNqProvDelete(Provider
);
484 /* Get the next provider */
485 NextProvider
= WsNqNextProvider(NsQuery
, NextProvider
);
490 /* Check if we had an error somewhere */
491 if (ErrorCode
== SOCKET_ERROR
)
494 while (!IsListEmpty(&NsQuery
->ProviderList
))
496 /* Remove this provider */
497 Entry
= RemoveHeadList(&NsQuery
->ProviderList
);
499 /* Get the failed provider and delete it */
500 Provider
= CONTAINING_RECORD(Entry
, NSQUERY_PROVIDER
, QueryLink
);
501 WsNqProvDelete(Provider
);
506 /* Set the active provider */
507 Entry
= NsQuery
->ProviderList
.Flink
;
508 NsQuery
->ActiveProvider
= CONTAINING_RECORD(Entry
,
519 WsNqNextProvider(IN PNSQUERY Query
,
520 IN PNSQUERY_PROVIDER Provider
)
522 PNSQUERY_PROVIDER NextProvider
= NULL
;
525 /* Get the first entry and get its provider */
526 Entry
= Provider
->QueryLink
.Flink
;
527 if (Entry
!= &Query
->ProviderList
)
529 /* Get the current provider */
530 NextProvider
= CONTAINING_RECORD(Entry
, NSQUERY_PROVIDER
, QueryLink
);
539 WsNqPreviousProvider(IN PNSQUERY Query
,
540 IN PNSQUERY_PROVIDER Provider
)
542 PNSQUERY_PROVIDER NextProvider
= NULL
;
545 /* Get the first entry and get its provider */
546 Entry
= Provider
->QueryLink
.Blink
;
547 if (Entry
!= &Query
->ProviderList
)
549 /* Get the current provider */
550 NextProvider
= CONTAINING_RECORD(Entry
, NSQUERY_PROVIDER
, QueryLink
);
559 WsNqAddProvider(IN PNSQUERY Query
,
560 IN PNS_PROVIDER Provider
)
562 PNSQUERY_PROVIDER QueryProvider
;
565 /* Allocate a new Query Provider */
566 if ((QueryProvider
= WsNqProvAllocate()))
569 WsNqProvInitialize(QueryProvider
, Provider
);
571 /* Insert it into the provider list */
572 InsertTailList(&Query
->ProviderList
, &QueryProvider
->QueryLink
);
577 SetLastError(WSASYSCALLFAILURE
);