Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygennsquery.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS WinSock 2 API 00004 * FILE: nsquery.c 00005 * PURPOSE: Namespace Query Object 00006 * PROGRAMMER: Alex Ionescu (alex@relsoft.net) 00007 */ 00008 00009 /* INCLUDES ******************************************************************/ 00010 #include "ws2_32.h" 00011 00012 /* DATA **********************************************************************/ 00013 00014 #define WsNqLock() EnterCriticalSection((LPCRITICAL_SECTION)&NsQuery->Lock); 00015 #define WsNqUnlock() LeaveCriticalSection((LPCRITICAL_SECTION)&NsQuery->Lock); 00016 00017 /* FUNCTIONS *****************************************************************/ 00018 00019 PNSQUERY 00020 WSAAPI 00021 WsNqAllocate(VOID) 00022 { 00023 PNSQUERY NsQuery; 00024 00025 /* Allocate the object */ 00026 NsQuery = HeapAlloc(WsSockHeap, HEAP_ZERO_MEMORY, sizeof(*NsQuery)); 00027 00028 /* Set non-zero fields */ 00029 NsQuery->Signature = ~0xBEADFACE; 00030 InitializeListHead(&NsQuery->ProviderList); 00031 NsQuery->TryAgain = TRUE; 00032 00033 /* Return it */ 00034 return NsQuery; 00035 } 00036 00037 DWORD 00038 WSAAPI 00039 WsNqInitialize(IN PNSQUERY Query) 00040 { 00041 /* Initialize the lock */ 00042 InitializeCriticalSection((LPCRITICAL_SECTION)&Query->Lock); 00043 00044 /* Set initial reference count and signature */ 00045 Query->RefCount = 1; 00046 Query->Signature = 0xBEADFACE; 00047 00048 /* Return success */ 00049 return ERROR_SUCCESS; 00050 } 00051 00052 BOOL 00053 WSAAPI 00054 WsNqValidateAndReference(IN PNSQUERY Query) 00055 { 00056 /* Check the signature first */ 00057 if (Query->Signature != 0xBEADFACE) return FALSE; 00058 00059 /* Validate the reference count */ 00060 if (!Query->RefCount) return FALSE; 00061 00062 /* Increase reference count */ 00063 InterlockedIncrement(&Query->RefCount); 00064 00065 /* Return success */ 00066 return TRUE; 00067 } 00068 00069 VOID 00070 WSAAPI 00071 WsNqDelete(IN PNSQUERY NsQuery) 00072 { 00073 PNSQUERY_PROVIDER Provider; 00074 PLIST_ENTRY Entry; 00075 00076 /* Make sure that we got initialized */ 00077 if (!NsQuery->ProviderList.Flink) return; 00078 00079 /* Loop the provider list */ 00080 while (!IsListEmpty(&NsQuery->ProviderList)) 00081 { 00082 /* Remove the entry */ 00083 Entry = RemoveHeadList(&NsQuery->ProviderList); 00084 00085 /* Get the provider */ 00086 Provider = CONTAINING_RECORD(Entry, NSQUERY_PROVIDER, QueryLink); 00087 00088 /* Delete it */ 00089 WsNqProvDelete(Provider); 00090 } 00091 00092 /* Remove the signature and delete the lock */ 00093 NsQuery->Signature = ~0xBEADFACE; 00094 DeleteCriticalSection((LPCRITICAL_SECTION)&NsQuery->Lock); 00095 00096 /* Free us */ 00097 HeapFree(WsSockHeap, 0, NsQuery); 00098 } 00099 00100 VOID 00101 WSAAPI 00102 WsNqDereference(IN PNSQUERY Query) 00103 { 00104 /* Decrease the reference count and check if it's zero */ 00105 if (!InterlockedDecrement(&Query->RefCount)) 00106 { 00107 /* Delete us*/ 00108 WsNqDelete(Query); 00109 } 00110 } 00111 00112 BOOL 00113 WSAAPI 00114 WsNqBeginEnumerationProc(PVOID Context, 00115 PNSCATALOG_ENTRY Entry) 00116 { 00117 PNS_PROVIDER Provider; 00118 BOOLEAN GoOn = TRUE; 00119 PENUM_CONTEXT EnumContext = (PENUM_CONTEXT)Context; 00120 PNSQUERY NsQuery = EnumContext->NsQuery; 00121 DWORD NamespaceId = Entry->NamespaceId; 00122 00123 /* Match the namespace ID, protocols and make sure it's enabled */ 00124 if ((((EnumContext->lpqsRestrictions->dwNameSpace == NamespaceId) || 00125 (EnumContext->lpqsRestrictions->dwNameSpace == NS_ALL)) && 00126 (!(EnumContext->lpqsRestrictions->dwNumberOfProtocols) || 00127 (WsNcMatchProtocols(NamespaceId, 00128 Entry->AddressFamily, 00129 EnumContext->lpqsRestrictions)))) && 00130 (Entry->Enabled)) 00131 { 00132 /* Get the provider */ 00133 if (!(Provider = Entry->Provider)) 00134 { 00135 /* None was laoded, load it */ 00136 if ((WsNcLoadProvider(EnumContext->Catalog, Entry) != ERROR_SUCCESS)) 00137 { 00138 /* return fake success */ 00139 return TRUE; 00140 } 00141 00142 /* Set the provider */ 00143 Provider = Entry->Provider; 00144 } 00145 00146 /* Add it to the query */ 00147 if (!(WsNqAddProvider(NsQuery, Provider))) 00148 { 00149 /* We failed */ 00150 EnumContext->ErrorCode = WSASYSCALLFAILURE; 00151 GoOn = FALSE; 00152 } 00153 } 00154 00155 /* Return to caller */ 00156 return GoOn; 00157 } 00158 00159 DWORD 00160 WSAAPI 00161 WsNqLookupServiceEnd(IN PNSQUERY NsQuery) 00162 { 00163 PNSQUERY_PROVIDER Provider; 00164 PLIST_ENTRY Entry; 00165 00166 /* Protect us from closure */ 00167 WsNqLock(); 00168 NsQuery->ShuttingDown = TRUE; 00169 00170 /* Get the list and loop */ 00171 Entry = NsQuery->ProviderList.Flink; 00172 while (Entry != &NsQuery->ProviderList) 00173 { 00174 /* Get the provider */ 00175 Provider = CONTAINING_RECORD(Entry, NSQUERY_PROVIDER, QueryLink); 00176 00177 /* Call its routine */ 00178 WsNqProvLookupServiceEnd(Provider); 00179 00180 /* Move to the next one */ 00181 Entry = Entry->Flink; 00182 } 00183 00184 /* Release lock and return success */ 00185 WsNqUnlock(); 00186 return ERROR_SUCCESS; 00187 } 00188 00189 DWORD 00190 WSAAPI 00191 WsNqLookupServiceNext(IN PNSQUERY NsQuery, 00192 IN DWORD ControlFlags, 00193 OUT PDWORD BufferLength, 00194 OUT LPWSAQUERYSETW Results) 00195 { 00196 PNSQUERY_PROVIDER Provider, NextProvider; 00197 INT ErrorCode = SOCKET_ERROR, OldErrorCode; 00198 PLIST_ENTRY Entry; 00199 00200 /* Make sure we're not shutting down */ 00201 if (!NsQuery->ShuttingDown) 00202 { 00203 /* Acquire query lock */ 00204 WsNqLock(); 00205 00206 /* Check if we already have an active provider */ 00207 NextProvider = NsQuery->ActiveProvider; 00208 if (!NextProvider) 00209 { 00210 /* Make sure we have a current provider */ 00211 if (!NsQuery->CurrentProvider) 00212 { 00213 /* We don't; fail */ 00214 WsNqUnlock(); 00215 SetLastError(WSA_E_NO_MORE); 00216 return SOCKET_ERROR; 00217 } 00218 00219 /* Get the first provider on the list and start looping */ 00220 Entry = NsQuery->ProviderList.Blink; 00221 NextProvider = CONTAINING_RECORD(Entry, NSQUERY_PROVIDER, QueryLink); 00222 while (NextProvider) 00223 { 00224 /* Check if this is a new-style provider */ 00225 if (NextProvider->Provider->Service.NSPIoctl) 00226 { 00227 /* Remove it and re-add it on top */ 00228 RemoveEntryList(&NextProvider->QueryLink); 00229 InsertHeadList(&NsQuery->ProviderList, &NextProvider->QueryLink); 00230 00231 /* Set it as the active provider and exit the loop */ 00232 NsQuery->ActiveProvider = NextProvider; 00233 break; 00234 } 00235 00236 /* Get the previous provider */ 00237 NextProvider = WsNqPreviousProvider(NsQuery, NextProvider); 00238 } 00239 } 00240 00241 /* Release the lock */ 00242 WsNqUnlock(); 00243 00244 /* Check if we have an active provider now */ 00245 if (NextProvider) 00246 { 00247 /* Start loop */ 00248 do 00249 { 00250 /* Call its routine */ 00251 ErrorCode = WsNqProvLookupServiceNext(NextProvider, 00252 ControlFlags, 00253 BufferLength, 00254 Results); 00255 /* Check for error or shutdown */ 00256 if ((ErrorCode == ERROR_SUCCESS) || 00257 (GetLastError() == WSAEFAULT) || (NsQuery->ShuttingDown)) 00258 { 00259 /* Get out */ 00260 break; 00261 } 00262 00263 /* Acquire Query Lock */ 00264 WsNqLock(); 00265 00266 /* Save the current active provider */ 00267 Provider = NsQuery->ActiveProvider; 00268 00269 /* Check if one exists */ 00270 if (Provider) 00271 { 00272 /* Get the next one */ 00273 NextProvider = WsNqNextProvider(NsQuery, 00274 NsQuery->ActiveProvider); 00275 00276 /* Was the old provider our active? */ 00277 if (Provider == NsQuery->ActiveProvider) 00278 { 00279 /* Change our active provider to the new one */ 00280 NsQuery->ActiveProvider = NextProvider; 00281 } 00282 } 00283 else 00284 { 00285 /* No next provider */ 00286 NextProvider = NULL; 00287 } 00288 00289 /* Check if we failed and if we can try again */ 00290 if (!(NextProvider) && 00291 (ErrorCode == SOCKET_ERROR) && 00292 (NsQuery->TryAgain)) 00293 { 00294 /* Save the error code so RAS doesn't overwrite it */ 00295 OldErrorCode = GetLastError(); 00296 00297 /* Make sure we won't try for a 3rd time */ 00298 NsQuery->TryAgain = FALSE; 00299 00300 /* Call the helper to auto-dial */ 00301 if (WSAttemptAutodialName(NsQuery->QuerySet)) 00302 { 00303 /* It suceeded, so we'll delete the current state. */ 00304 while (!IsListEmpty(&NsQuery->ProviderList)) 00305 { 00306 /* Remove the entry and get its provider */ 00307 Entry = RemoveHeadList(&NsQuery->ProviderList); 00308 Provider = CONTAINING_RECORD(Entry, 00309 NSQUERY_PROVIDER, 00310 QueryLink); 00311 00312 /* Reset it */ 00313 WsNqProvLookupServiceEnd(Provider); 00314 WsNqProvDelete(Provider); 00315 } 00316 00317 /* Start a new query */ 00318 if (!WsNqLookupServiceBegin(NsQuery, 00319 NsQuery->QuerySet, 00320 NsQuery->ControlFlags, 00321 NsQuery->Catalog)) 00322 { 00323 /* New query succeeded, set active provider now */ 00324 NsQuery->ActiveProvider = 00325 WsNqNextProvider(NsQuery, 00326 NsQuery->ActiveProvider); 00327 } 00328 } 00329 else 00330 { 00331 /* Reset the error code */ 00332 SetLastError(OldErrorCode); 00333 } 00334 } 00335 00336 /* Release lock */ 00337 WsNqUnlock(); 00338 00339 /* Keep looping as long as there is a provider */ 00340 } while (NextProvider); 00341 } 00342 } 00343 else 00344 { 00345 /* We are shuting down; fail */ 00346 SetLastError(WSAECANCELLED); 00347 } 00348 00349 /* Return */ 00350 return ErrorCode; 00351 } 00352 00353 DWORD 00354 WSAAPI 00355 WsNqLookupServiceBegin(IN PNSQUERY NsQuery, 00356 IN LPWSAQUERYSETW Restrictions, 00357 IN DWORD ControlFlags, 00358 IN PNSCATALOG Catalog) 00359 { 00360 WSASERVICECLASSINFOW ClassInfo; 00361 PNSQUERY_PROVIDER Provider; 00362 LPWSASERVICECLASSINFOW pClassInfo = NULL; 00363 PNSQUERY_PROVIDER NextProvider; 00364 PLIST_ENTRY Entry; 00365 INT ErrorCode; 00366 DWORD ClassInfoSize; 00367 PNSCATALOG_ENTRY CatalogEntry; 00368 ENUM_CONTEXT EnumContext; 00369 BOOLEAN TryAgain; 00370 00371 /* Check for RAS Auto-dial attempt */ 00372 if (NsQuery->TryAgain) 00373 { 00374 /* Make a copy of the query set */ 00375 ErrorCode = CopyQuerySetW(Restrictions, &NsQuery->QuerySet); 00376 TryAgain = (ErrorCode == ERROR_SUCCESS); 00377 00378 /* Check if we'll try again */ 00379 if (!TryAgain) 00380 { 00381 /* We won't, fail */ 00382 SetLastError(ErrorCode); 00383 ErrorCode = SOCKET_ERROR; 00384 NsQuery->TryAgain = FALSE; 00385 goto error; 00386 } 00387 00388 /* Cache the information for a restart */ 00389 NsQuery->ControlFlags = ControlFlags; 00390 NsQuery->Catalog = Catalog; 00391 } 00392 00393 /* Check if we have a specific ID */ 00394 if (Restrictions->lpNSProviderId) 00395 { 00396 /* Get the provider */ 00397 ErrorCode = WsNcGetCatalogFromProviderId(Catalog, 00398 Restrictions->lpNSProviderId, 00399 &CatalogEntry); 00400 /* Check for success */ 00401 if (ErrorCode != ERROR_SUCCESS) 00402 { 00403 /* Fail */ 00404 SetLastError(WSAEINVAL); 00405 ErrorCode = SOCKET_ERROR; 00406 goto error; 00407 } 00408 else 00409 { 00410 /* Add this provider */ 00411 WsNqAddProvider(NsQuery, CatalogEntry->Provider); 00412 } 00413 } 00414 else 00415 { 00416 /* Setup the lookup context */ 00417 EnumContext.lpqsRestrictions = Restrictions; 00418 EnumContext.ErrorCode = ERROR_SUCCESS; 00419 EnumContext.NsQuery = NsQuery; 00420 EnumContext.Catalog = Catalog; 00421 00422 /* Do a lookup for every entry */ 00423 WsNcEnumerateCatalogItems(Catalog, 00424 WsNqBeginEnumerationProc, 00425 &EnumContext); 00426 ErrorCode = EnumContext.ErrorCode; 00427 00428 /* Check for success */ 00429 if (ErrorCode != ERROR_SUCCESS) 00430 { 00431 /* Fail */ 00432 SetLastError(WSAEINVAL); 00433 ErrorCode = SOCKET_ERROR; 00434 goto error; 00435 } 00436 } 00437 00438 /* Get the class information */ 00439 ClassInfo.lpServiceClassId = Restrictions->lpServiceClassId; 00440 ErrorCode = WsNcGetServiceClassInfo(Catalog, &ClassInfoSize, &ClassInfo); 00441 00442 /* Check if more buffer space is needed */ 00443 if ((ErrorCode == SOCKET_ERROR) && (GetLastError() == WSAEFAULT)) 00444 { 00445 /* FIXME: The WS 2.2 spec hasn't been finalized yet on this... */ 00446 } 00447 else 00448 { 00449 /* Assume sucess */ 00450 ErrorCode = ERROR_SUCCESS; 00451 } 00452 00453 /* Check if the provider list is empty */ 00454 if (IsListEmpty(&NsQuery->ProviderList)) 00455 { 00456 /* We don't have any providers to handle this! */ 00457 ErrorCode = SOCKET_ERROR; 00458 SetLastError(WSASERVICE_NOT_FOUND); 00459 goto error; 00460 } 00461 00462 /* Get the first provider and loop */ 00463 Entry = NsQuery->ProviderList.Flink; 00464 NextProvider = CONTAINING_RECORD(Entry, NSQUERY_PROVIDER, QueryLink); 00465 while (NextProvider) 00466 { 00467 /* Call it */ 00468 ErrorCode = WsNqProvLookupServiceBegin(NextProvider, 00469 Restrictions, 00470 pClassInfo, 00471 ControlFlags); 00472 /* Check for error */ 00473 if (ErrorCode == SOCKET_ERROR) 00474 { 00475 /* Remove this provider, get the next one, delete the old one */ 00476 Provider = NextProvider; 00477 NextProvider = WsNqNextProvider(NsQuery, NextProvider); 00478 RemoveEntryList(&Provider->QueryLink); 00479 WsNqProvDelete(Provider); 00480 } 00481 else 00482 { 00483 /* Get the next provider */ 00484 NextProvider = WsNqNextProvider(NsQuery, NextProvider); 00485 } 00486 } 00487 00488 error: 00489 /* Check if we had an error somewhere */ 00490 if (ErrorCode == SOCKET_ERROR) 00491 { 00492 /* Loop the list */ 00493 while (!IsListEmpty(&NsQuery->ProviderList)) 00494 { 00495 /* Remove this provider */ 00496 Entry = RemoveHeadList(&NsQuery->ProviderList); 00497 00498 /* Get the failed provider and delete it */ 00499 Provider = CONTAINING_RECORD(Entry, NSQUERY_PROVIDER, QueryLink); 00500 WsNqProvDelete(Provider); 00501 } 00502 } 00503 else 00504 { 00505 /* Set the active provider */ 00506 Entry = NsQuery->ProviderList.Flink; 00507 NsQuery->ActiveProvider = CONTAINING_RECORD(Entry, 00508 NSQUERY_PROVIDER, 00509 QueryLink); 00510 } 00511 00512 /* Return */ 00513 return ErrorCode; 00514 } 00515 00516 PNSQUERY_PROVIDER 00517 WSAAPI 00518 WsNqNextProvider(IN PNSQUERY Query, 00519 IN PNSQUERY_PROVIDER Provider) 00520 { 00521 PNSQUERY_PROVIDER NextProvider = NULL; 00522 PLIST_ENTRY Entry; 00523 00524 /* Get the first entry and get its provider */ 00525 Entry = Provider->QueryLink.Flink; 00526 if (Entry != &Query->ProviderList) 00527 { 00528 /* Get the current provider */ 00529 NextProvider = CONTAINING_RECORD(Entry, NSQUERY_PROVIDER, QueryLink); 00530 } 00531 00532 /* Return it */ 00533 return NextProvider; 00534 } 00535 00536 PNSQUERY_PROVIDER 00537 WSAAPI 00538 WsNqPreviousProvider(IN PNSQUERY Query, 00539 IN PNSQUERY_PROVIDER Provider) 00540 { 00541 PNSQUERY_PROVIDER NextProvider = NULL; 00542 PLIST_ENTRY Entry; 00543 00544 /* Get the first entry and get its provider */ 00545 Entry = Provider->QueryLink.Blink; 00546 if (Entry != &Query->ProviderList) 00547 { 00548 /* Get the current provider */ 00549 NextProvider = CONTAINING_RECORD(Entry, NSQUERY_PROVIDER, QueryLink); 00550 } 00551 00552 /* Return it */ 00553 return NextProvider; 00554 } 00555 00556 DWORD 00557 WSAAPI 00558 WsNqAddProvider(IN PNSQUERY Query, 00559 IN PNS_PROVIDER Provider) 00560 { 00561 PNSQUERY_PROVIDER QueryProvider; 00562 DWORD Return = TRUE; 00563 00564 /* Allocate a new Query Provider */ 00565 if ((QueryProvider = WsNqProvAllocate())) 00566 { 00567 /* Initialize it */ 00568 WsNqProvInitialize(QueryProvider, Provider); 00569 00570 /* Insert it into the provider list */ 00571 InsertTailList(&Query->ProviderList, &QueryProvider->QueryLink); 00572 } 00573 else 00574 { 00575 /* We failed */ 00576 SetLastError(WSASYSCALLFAILURE); 00577 Return = FALSE; 00578 } 00579 00580 /* Return */ 00581 return Return; 00582 } 00583 00584 Generated on Sun May 27 2012 04:27:10 for ReactOS by
1.7.6.1
|