2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS WinSock 2 API
5 * PURPOSE: Namespace Catalog Object
6 * PROGRAMMER: Alex Ionescu (alex@relsoft.net)
9 /* INCLUDES ******************************************************************/
12 /* DATA **********************************************************************/
14 #define NSCATALOG_NAME "NameSpace_Catalog5"
15 #define WsNcLock() EnterCriticalSection((LPCRITICAL_SECTION)&Catalog->Lock);
16 #define WsNcUnlock() LeaveCriticalSection((LPCRITICAL_SECTION)&Catalog->Lock);
18 /* FUNCTIONS *****************************************************************/
26 /* Allocate the catalog */
27 Catalog
= HeapAlloc(WsSockHeap
, HEAP_ZERO_MEMORY
, sizeof(*Catalog
));
35 WsNcOpen(IN PNSCATALOG Catalog
,
39 DWORD CreateDisposition
;
40 HKEY CatalogKey
, NewKey
;
41 //DWORD CatalogEntries = 0;
42 DWORD RegType
= REG_DWORD
;
43 DWORD RegSize
= sizeof(DWORD
);
47 /* Initialize the catalog lock and namespace list */
48 InitializeCriticalSection((LPCRITICAL_SECTION
)&Catalog
->Lock
);
49 InitializeListHead(&Catalog
->CatalogList
);
51 /* Open the Catalog Key */
52 ErrorCode
= RegOpenKeyEx(ParentKey
,
58 /* If we didn't find the key, create it */
59 if (ErrorCode
== ERROR_SUCCESS
)
61 /* Fake that we opened an existing key */
62 CreateDisposition
= REG_OPENED_EXISTING_KEY
;
64 else if (ErrorCode
== ERROR_FILE_NOT_FOUND
)
66 /* Create the Catalog Name */
67 ErrorCode
= RegCreateKeyEx(ParentKey
,
71 REG_OPTION_NON_VOLATILE
,
78 /* Fail if that didn't work */
79 if (ErrorCode
!= ERROR_SUCCESS
) return FALSE
;
81 /* Check if we had to create the key */
82 if (CreateDisposition
== REG_CREATED_NEW_KEY
)
84 /* Write the count of entries (0 now) */
85 ErrorCode
= RegSetValueEx(CatalogKey
,
86 "Num_Catalog_Entries",
91 if (ErrorCode
!= ERROR_SUCCESS
)
93 /* Close the key and fail */
94 RegCloseKey(CatalogKey
);
98 /* Write the first catalog entry Uniqe ID */
100 ErrorCode
= RegSetValueEx(CatalogKey
,
106 if (ErrorCode
!= ERROR_SUCCESS
)
108 /* Close the key and fail */
109 RegCloseKey(CatalogKey
);
113 /* Create a key for this entry */
114 ErrorCode
= RegCreateKeyEx(CatalogKey
,
118 REG_OPTION_NON_VOLATILE
,
123 if (ErrorCode
!= ERROR_SUCCESS
)
125 /* Close the key and fail */
126 RegCloseKey(CatalogKey
);
130 /* Close the key since we don't need it */
135 /* Read the serial number */
136 ErrorCode
= RegQueryValueEx(CatalogKey
,
143 /* Check if it's missing for some reason */
144 if (ErrorCode
!= ERROR_SUCCESS
)
146 /* Write the first catalog entry Unique ID */
148 ErrorCode
= RegSetValueEx(CatalogKey
,
157 /* Set the Catalog Key */
158 Catalog
->CatalogKey
= CatalogKey
;
164 WsNcInitializeFromRegistry(IN PNSCATALOG Catalog
,
166 IN HANDLE CatalogEvent
)
168 INT ErrorCode
= WSASYSCALLFAILURE
;
170 /* Open the catalog */
171 if (WsNcOpen(Catalog
, ParentKey
))
174 ErrorCode
= WsNcRefreshFromRegistry(Catalog
, CatalogEvent
);
177 /* Return the status */
183 WsNcRefreshFromRegistry(IN PNSCATALOG Catalog
,
184 IN HANDLE CatalogEvent
)
187 BOOLEAN LocalEvent
= FALSE
;
188 LIST_ENTRY LocalList
;
191 DWORD CatalogEntries
;
192 PNSCATALOG_ENTRY CatalogEntry
;
195 DWORD RegType
= REG_DWORD
;
196 DWORD RegSize
= sizeof(DWORD
);
199 /* Check if we got an event */
202 /* Create an event ourselves */
203 CatalogEvent
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
204 if (!CatalogEvent
) return WSASYSCALLFAILURE
;
208 /* Lock the catalog */
211 /* Initialize our local list for the loop */
212 InitializeListHead(&LocalList
);
217 /* Setup notifications for the catalog entry */
218 ErrorCode
= WsSetupCatalogProtection(Catalog
->CatalogKey
,
221 if (ErrorCode
!= ERROR_SUCCESS
) break;
223 /* Check if we've changed till now */
224 if (UniqueId
== Catalog
->UniqueId
)
226 /* We haven't, so return */
227 ErrorCode
= ERROR_SUCCESS
;
231 /* Now Open the Entries */
232 ErrorCode
= RegOpenKeyEx(Catalog
->CatalogKey
,
237 if (ErrorCode
!= ERROR_SUCCESS
)
239 /* Critical failure */
240 ErrorCode
= WSASYSCALLFAILURE
;
244 /* Find out how many there are */
245 ErrorCode
= RegQueryValueEx(Catalog
->CatalogKey
,
246 "Num_Catalog_Entries",
249 (LPBYTE
)&CatalogEntries
,
251 if (ErrorCode
!= ERROR_SUCCESS
)
253 /* Critical failure */
254 ErrorCode
= WSASYSCALLFAILURE
;
258 /* Initialize them all */
259 for (i
= 1; i
<= CatalogEntries
; i
++)
261 /* Allocate a Catalog Entry Structure */
262 CatalogEntry
= WsNcEntryAllocate();
265 /* Not enough memory, fail */
266 ErrorCode
= WSA_NOT_ENOUGH_MEMORY
;
270 /* Initialize it from the Registry Key */
271 ErrorCode
= WsNcEntryInitializeFromRegistry(CatalogEntry
,
274 if (ErrorCode
!= ERROR_SUCCESS
)
276 /* We failed to get it, dereference the entry and leave */
277 WsNcEntryDereference(CatalogEntry
);
281 /* Insert it to our List */
282 InsertTailList(&LocalList
, &CatalogEntry
->CatalogLink
);
285 /* Close the catalog key */
286 RegCloseKey(EntriesKey
);
288 /* Check if we changed during our read and if we have success */
289 NewChangesMade
= WsCheckCatalogState(CatalogEvent
);
290 if (!NewChangesMade
&& ErrorCode
== ERROR_SUCCESS
)
292 /* All is good, update the protocol list */
293 WsNcUpdateNamespaceList(Catalog
, &LocalList
);
295 /* Update and return */
296 Catalog
->UniqueId
= UniqueId
;
300 /* We failed and/or catalog data changed, free what we did till now */
301 while (!IsListEmpty(&LocalList
))
303 /* Get the LP Catalog Item */
304 Entry
= RemoveHeadList(&LocalList
);
305 CatalogEntry
= CONTAINING_RECORD(Entry
, NSCATALOG_ENTRY
, CatalogLink
);
308 WsNcEntryDereference(CatalogEntry
);
310 } while (NewChangesMade
);
312 /* Release the lock */
315 /* Close the event, if any was created by us */
316 if (LocalEvent
) CloseHandle(CatalogEvent
);
324 WsNcEnumerateCatalogItems(IN PNSCATALOG Catalog
,
325 IN PNSCATALOG_ENUMERATE_PROC Callback
,
329 PNSCATALOG_ENTRY CatalogEntry
;
332 /* Lock the catalog */
335 /* Loop the entries */
336 Entry
= Catalog
->CatalogList
.Flink
;
337 while (GoOn
&& (Entry
!= &Catalog
->CatalogList
))
340 CatalogEntry
= CONTAINING_RECORD(Entry
, NSCATALOG_ENTRY
, CatalogLink
);
342 /* Move to the next one and call the callback */
343 Entry
= Entry
->Flink
;
344 GoOn
= Callback(Context
, CatalogEntry
);
353 WsNcLoadProvider(IN PNSCATALOG Catalog
,
354 IN PNSCATALOG_ENTRY CatalogEntry
)
356 INT ErrorCode
= ERROR_SUCCESS
;
357 PNS_PROVIDER Provider
;
359 /* Lock the catalog */
362 /* Check if we have a provider already */
363 if (!CatalogEntry
->Provider
)
365 /* Allocate a provider */
366 if ((Provider
= WsNpAllocate()))
369 ErrorCode
= WsNpInitialize(Provider
,
370 CatalogEntry
->DllPath
,
371 &CatalogEntry
->ProviderId
);
374 if (ErrorCode
== ERROR_SUCCESS
)
376 /* Set the provider */
377 WsNcEntrySetProvider(CatalogEntry
, Provider
);
381 WsNpDereference(Provider
);
386 ErrorCode
= WSA_NOT_ENOUGH_MEMORY
;
390 /* Release the lock */
397 WsNcGetServiceClassInfo(IN PNSCATALOG Catalog
,
398 IN OUT LPDWORD BugSize
,
399 IN OUT LPWSASERVICECLASSINFOW lpServiceClassInfo
)
401 /* Not yet implemented in the spec? */
402 SetLastError(ERROR_SUCCESS
);
408 WsNcUpdateNamespaceList(IN PNSCATALOG Catalog
,
412 PNSCATALOG_ENTRY CatalogEntry
, OldCatalogEntry
;
415 /* First move from our list to the old one */
416 InsertHeadList(&Catalog
->CatalogList
, &TempList
);
417 RemoveEntryList(&Catalog
->CatalogList
);
418 InitializeListHead(&Catalog
->CatalogList
);
420 /* Loop every item on the list */
421 while (!IsListEmpty(List
))
423 /* Get the catalog entry */
424 Entry
= RemoveHeadList(List
);
425 CatalogEntry
= CONTAINING_RECORD(Entry
, NSCATALOG_ENTRY
, CatalogLink
);
427 /* Check if this item is already on our list */
428 Entry
= TempList
.Flink
;
429 while (Entry
!= &TempList
)
431 /* Get the catalog entry */
432 OldCatalogEntry
= CONTAINING_RECORD(Entry
, NSCATALOG_ENTRY
, CatalogLink
);
433 Entry
= Entry
->Flink
;
435 /* Check if they match */
436 if (memcmp(&CatalogEntry
->ProviderId
,
437 &OldCatalogEntry
->ProviderId
,
440 /* We have a match, use the old item instead */
441 WsNcEntryDereference(CatalogEntry
);
442 CatalogEntry
= OldCatalogEntry
;
443 RemoveEntryList(&CatalogEntry
->CatalogLink
);
445 /* Decrease the number of protocols we have */
446 Catalog
->ItemCount
--;
452 InsertTailList(&Catalog
->CatalogList
, &CatalogEntry
->CatalogLink
);
453 Catalog
->ItemCount
++;
456 /* If there's anything left on the temporary list */
457 while (!IsListEmpty(&TempList
))
460 Entry
= RemoveHeadList(&TempList
);
461 CatalogEntry
= CONTAINING_RECORD(Entry
, NSCATALOG_ENTRY
, CatalogLink
);
464 Catalog
->ItemCount
--;
465 WsNcEntryDereference(CatalogEntry
);
471 WsNcGetCatalogFromProviderId(IN PNSCATALOG Catalog
,
472 IN LPGUID ProviderId
,
473 OUT PNSCATALOG_ENTRY
*CatalogEntry
)
475 PLIST_ENTRY NextEntry
= Catalog
->CatalogList
.Flink
;
476 PNSCATALOG_ENTRY Entry
;
478 /* Lock the catalog */
481 /* Match the Id with all the entries in the List */
482 while (NextEntry
!= &Catalog
->CatalogList
)
484 /* Get the Current Entry */
485 Entry
= CONTAINING_RECORD(NextEntry
, NSCATALOG_ENTRY
, CatalogLink
);
486 NextEntry
= NextEntry
->Flink
;
488 /* Check if this is the Catalog Entry ID we want */
489 if (!(memcmp(&Entry
->ProviderId
, ProviderId
, sizeof(GUID
))))
491 /* Check if it doesn't already have a provider */
492 if (!Entry
->Provider
)
494 /* Match, load the Provider */
495 WsNcLoadProvider(Catalog
, Entry
);
498 /* Reference the entry and return it */
499 InterlockedIncrement(&Entry
->RefCount
);
500 *CatalogEntry
= Entry
;
505 /* Release the catalog */
509 return ERROR_SUCCESS
;
514 WsNcMatchProtocols(IN DWORD NameSpace
,
515 IN LONG AddressFamily
,
516 IN LPWSAQUERYSETW QuerySet
)
518 DWORD ProtocolCount
= QuerySet
->dwNumberOfProtocols
;
519 LPAFPROTOCOLS AfpProtocols
= QuerySet
->lpafpProtocols
;
522 /* Check for valid family */
523 if (AddressFamily
!= -1)
525 /* Check if it's the magic */
526 if (AddressFamily
== AF_UNSPEC
) return TRUE
;
527 Family
= AddressFamily
;
531 /* No family given, check for namespace */
532 if (NameSpace
== NS_SAP
)
539 /* Other namespace, it's valid */
544 /* Now try to get a match */
545 while (ProtocolCount
--)
547 /* Check this protocol entry */
548 if ((AfpProtocols
->iAddressFamily
== AF_UNSPEC
) ||
549 (AfpProtocols
->iAddressFamily
== Family
))
555 /* Move to the next one */
565 WsNcRemoveCatalogItem(IN PNSCATALOG Catalog
,
566 IN PNSCATALOG_ENTRY Entry
)
568 /* Remove the entry from the list */
569 RemoveEntryList(&Entry
->CatalogLink
);
571 /* Decrease our count */
572 Catalog
->ItemCount
--;
577 WsNcDelete(IN PNSCATALOG Catalog
)
580 PNSCATALOG_ENTRY CatalogEntry
;
582 /* Check if we're initialized */
583 if (!Catalog
->CatalogList
.Flink
) return;
588 /* Loop every entry */
589 Entry
= Catalog
->CatalogList
.Flink
;
590 while (Entry
!= &Catalog
->CatalogList
)
593 CatalogEntry
= CONTAINING_RECORD(Entry
, NSCATALOG_ENTRY
, CatalogLink
);
596 WsNcRemoveCatalogItem(Catalog
, CatalogEntry
);
599 WsNcEntryDereference(CatalogEntry
);
601 /* Move to the next entry */
602 Entry
= Catalog
->CatalogList
.Flink
;
605 /* Check if the catalog key is opened */
606 if (Catalog
->CatalogKey
)
609 RegCloseKey(Catalog
->CatalogKey
);
610 Catalog
->CatalogKey
= NULL
;
613 /* Release and delete the lock */
615 DeleteCriticalSection((LPCRITICAL_SECTION
)&Catalog
->Lock
);
617 /* Delete the object */
618 HeapFree(WsSockHeap
, 0, Catalog
);