ReactOS 0.4.15-dev-7994-gb388cb6
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,
197 OUT LPWSAQUERYSETW Results)
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;
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);
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
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
BOOL Query(LPCTSTR *ServiceArgs, DWORD ArgCount, BOOL bExtended)
Definition: query.c:292
@ TryAgain
Definition: bl.h:896
#define ERROR_SUCCESS
Definition: deptool.c:10
#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
struct _ENUM_CONTEXT * PENUM_CONTEXT
_In_ NDIS_ERROR_CODE ErrorCode
Definition: ndis.h:4436
#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
static void Exit(void)
Definition: sock.c:1330
static LPWSAQUERYSETW
Definition: sock.c:90
base of all file and directory entries
Definition: entries.h:83
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
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:751
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:3771
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)
#define WSAECANCELLED
Definition: winerror.h:1990
#define WSASYSCALLFAILURE
Definition: winerror.h:1994
#define WSAEINVAL
Definition: winerror.h:1946
#define WSASERVICE_NOT_FOUND
Definition: winerror.h:1995
#define WSAEFAULT
Definition: winerror.h:1945
#define WSA_E_NO_MORE
Definition: winerror.h:1997
#define WSA_NOT_ENOUGH_MEMORY
Definition: winsock2.h:620
#define WSAAPI
Definition: winsock2.h:605
BOOL WINAPI WSAttemptAutodialName(IN CONST LPWSAQUERYSETW Restrictions)
Definition: winsock.c:58
#define SOCKET_ERROR
Definition: winsock.h:333
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