ReactOS  0.4.14-dev-98-gb0d4763
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_new/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 
21 WSAAPI
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 
40 DWORD
41 WSAAPI
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 
55 BOOL
56 WSAAPI
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 
72 VOID
73 WSAAPI
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 
103 VOID
104 WSAAPI
106 {
107  /* Decrease the reference count and check if it's zero */
108  if (!InterlockedDecrement(&Query->RefCount))
109  {
110  /* Delete us*/
111  WsNqDelete(Query);
112  }
113 }
114 
115 BOOL
116 WSAAPI
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 
162 DWORD
163 WSAAPI
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 
192 DWORD
193 WSAAPI
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 */
256  ErrorCode = WsNqProvLookupServiceNext(NextProvider,
257  ControlFlags,
258  BufferLength,
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 
345 DWORD
346 WSAAPI
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;
356  INT ErrorCode;
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 */
392  if (ErrorCode != ERROR_SUCCESS)
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 */
423  if (ErrorCode != ERROR_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 */
462  ErrorCode = WsNqProvLookupServiceBegin(NextProvider,
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 
482 Exit:
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 
511 WSAAPI
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 
531 WSAAPI
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 
550 BOOL
551 WSAAPI
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 
LPNSPIOCTL NSPIoctl
Definition: ws2spi.h:665
#define SOCKET_ERROR
Definition: winsock.h:333
#define IN
Definition: typedefs.h:38
DWORD WSAAPI WsNqInitialize(IN PNSQUERY Query)
Definition: nsquery.c:42
#define TRUE
Definition: types.h:120
#define WSAEFAULT
Definition: winerror.h:1945
_In_ NDIS_ERROR_CODE ErrorCode
Definition: ndis.h:4436
#define ERROR_SUCCESS
Definition: deptool.c:10
struct _Entry Entry
Definition: kefuncs.h:640
#define WSASERVICE_NOT_FOUND
Definition: winerror.h:1995
PNSCATALOG Catalog
Definition: ws2_32p.h:211
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
#define WSAEINVAL
Definition: winerror.h:1946
INT WSAAPI WsNcGetCatalogFromProviderId(IN PNSCATALOG Catalog, IN LPGUID ProviderId, OUT PNSCATALOG_ENTRY *CatalogEntry)
Definition: nscatalo.c:496
static LPWSAQUERYSETW
Definition: sock.c:91
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
#define WsNqUnlock()
Definition: nsquery.c:16
DWORD TryAgain
Definition: ws2_32p.h:157
#define InsertTailList(ListHead, Entry)
Definition: ws2_32p.h:121
DWORD WSAAPI WsNqLookupServiceBegin(IN PNSQUERY NsQuery, IN LPWSAQUERYSETW Restrictions, IN DWORD ControlFlags, IN PNSCATALOG Catalog)
Definition: nsquery.c:347
int32_t INT
Definition: typedefs.h:56
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
DWORD WSAAPI WsNqProvLookupServiceNext(IN PNSQUERY_PROVIDER QueryProvider, DWORD, PDWORD, LPWSAQUERYSETW QuerySet)
PNS_PROVIDER Provider
Definition: ws2_32p.h:117
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
LPWSAQUERYSETW lpqsRestrictions
Definition: ws2_32p.h:208
unsigned int BOOL
Definition: ntddk_ex.h:94
BOOL WINAPI WSAttemptAutodialName(IN CONST LPWSAQUERYSETW Restrictions)
Definition: winsock.c:58
_In_ ULONG BufferLength
Definition: usbdlib.h:225
BOOL WSAAPI WsNqAddProvider(IN PNSQUERY Query, IN PNS_PROVIDER Provider)
Definition: nsquery.c:552
struct _ENUM_CONTEXT * PENUM_CONTEXT
Definition: bl.h:897
DWORD WSAAPI WsNqLookupServiceNext(IN PNSQUERY NsQuery, IN DWORD ControlFlags, OUT PDWORD BufferLength, OUT LPWSAQUERYSETW Results)
Definition: nsquery.c:194
unsigned char BOOLEAN
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:751
smooth NULL
Definition: ftsmooth.c:416
PNSQUERY NsQuery
Definition: ws2_32p.h:210
#define NS_ALL
Definition: nspapi.h:8
PNSQUERY_PROVIDER WSAAPI WsNqNextProvider(IN PNSQUERY Query, IN PNSQUERY_PROVIDER Provider)
Definition: nsquery.c:512
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
DWORD WSAAPI WsNqLookupServiceEnd(IN PNSQUERY NsQuery)
Definition: nsquery.c:164
BOOL WSAAPI WsNqBeginEnumerationProc(PVOID Context, PNSCATALOG_ENTRY Entry)
Definition: nsquery.c:117
DWORD WSAAPI WsNqProvLookupServiceBegin(IN PNSQUERY_PROVIDER QueryProvider, IN LPWSAQUERYSETW QuerySet, IN LPWSASERVICECLASSINFOW ServiceClassInfo, IN DWORD)
Definition: nsprovid.c:216
INT WSAAPI WsNcLoadProvider(IN PNSCATALOG Catalog, IN PNSCATALOG_ENTRY CatalogEntry)
Definition: nscatalo.c:379
#define WSA_E_NO_MORE
Definition: winerror.h:1997
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
INT ErrorCode
Definition: ws2_32p.h:209
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)
LIST_ENTRY ProviderList
Definition: ws2_32p.h:150
static void Exit(void)
Definition: sock.c:1331
PNS_PROVIDER Provider
Definition: ws2_32p.h:125
#define WSAECANCELLED
Definition: winerror.h:1990
#define WsNqLock()
Definition: nsquery.c:15
INT WSAAPI CopyQuerySetW(IN LPWSAQUERYSETW UnicodeSet, OUT LPWSAQUERYSETW *UnicodeCopy)
Definition: qshelpr.c:1050
unsigned long DWORD
Definition: ntddk_ex.h:95
VOID WSAAPI WsNqProvDelete(IN PNSQUERY_PROVIDER QueryProvider)
Definition: nsprovid.c:45
#define SetLastError(x)
Definition: compat.h:409
BOOL Query(LPCTSTR *ServiceArgs, DWORD ArgCount, BOOL bExtended)
Definition: query.c:292
#define WSA_NOT_ENOUGH_MEMORY
Definition: winsock2.h:593
#define InterlockedDecrement
Definition: armddk.h:52
Definition: typedefs.h:117
VOID WSAAPI WsNcEnumerateCatalogItems(IN PNSCATALOG Catalog, IN PNSCATALOG_ENUMERATE_PROC Callback, IN PVOID Context)
Definition: nscatalo.c:350
LIST_ENTRY QueryLink
Definition: ws2_32p.h:116
#define WSASYSCALLFAILURE
Definition: winerror.h:1994
VOID WSAAPI WsNqDereference(IN PNSQUERY Query)
Definition: nsquery.c:105
INT WSAAPI WsNcGetServiceClassInfo(IN PNSCATALOG Catalog, IN OUT LPDWORD BugSize, IN OUT LPWSASERVICECLASSINFOW lpServiceClassInfo)
Definition: nscatalo.c:423
PNSQUERY WSAAPI WsNqAllocate(VOID)
Definition: nsquery.c:22
#define InterlockedIncrement
Definition: armddk.h:53
PNSQUERY_PROVIDER WSAAPI WsNqProvAllocate(VOID)
Definition: nsprovid.c:17
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define WSAAPI
Definition: winsock2.h:584
PNSQUERY_PROVIDER WSAAPI WsNqPreviousProvider(IN PNSQUERY Query, IN PNSQUERY_PROVIDER Provider)
Definition: nsquery.c:532
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
DWORD * PDWORD
Definition: pedump.c:68
NSP_ROUTINE Service
Definition: ws2_32p.h:111
#define OUT
Definition: typedefs.h:39
DWORD WSAAPI WsNqProvInitialize(IN PNSQUERY_PROVIDER QueryProvider, IN PNS_PROVIDER Provider)
Definition: nsprovid.c:30
BOOL WSAAPI WsNcMatchProtocols(IN DWORD NameSpace, IN LONG AddressFamily, IN LPWSAQUERYSETW QuerySet)
Definition: nscatalo.c:540
DWORD WSAAPI WsNqProvLookupServiceEnd(IN PNSQUERY_PROVIDER QueryProvider)
Definition: nsprovid.c:192
HANDLE WsSockHeap
Definition: dllmain.c:21
DWORD Signature
Definition: ws2_32p.h:147
#define HeapFree(x, y, z)
Definition: compat.h:394
base of all file and directory entries
Definition: entries.h:82
VOID WSAAPI WsNqDelete(IN PNSQUERY NsQuery)
Definition: nsquery.c:74
BOOL WSAAPI WsNqValidateAndReference(IN PNSQUERY Query)
Definition: nsquery.c:57