ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

nsquery.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.