2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS WinSock 2 API
4 * FILE: dll/win32/ws2_32_new/src/nscatalo.c
5 * PURPOSE: Namespace Catalog Object
6 * PROGRAMMER: Alex Ionescu (alex@relsoft.net)
9 /* INCLUDES ******************************************************************/
16 /* DATA **********************************************************************/
18 #define WsNcLock() EnterCriticalSection(&Catalog->Lock)
19 #define WsNcUnlock() LeaveCriticalSection(&Catalog->Lock)
21 /* FUNCTIONS *****************************************************************/
29 /* Allocate the catalog */
30 Catalog
= HeapAlloc(WsSockHeap
, HEAP_ZERO_MEMORY
, sizeof(*Catalog
));
38 WsNcOpen(IN PNSCATALOG Catalog
,
42 DWORD CreateDisposition
;
43 HKEY CatalogKey
, NewKey
;
44 DWORD RegType
= REG_DWORD
;
45 DWORD RegSize
= sizeof(DWORD
);
50 /* Initialize the catalog lock and namespace list */
51 InitializeCriticalSection(&Catalog
->Lock
);
52 InitializeListHead(&Catalog
->CatalogList
);
54 /* Read the catalog name */
55 ErrorCode
= RegQueryValueEx(ParentKey
,
56 "Current_NameSpace_Catalog",
62 CatalogKeyName
= HeapAlloc(WsSockHeap
, 0, RegSize
);
64 /* Read the catalog name */
65 ErrorCode
= RegQueryValueEx(ParentKey
,
66 "Current_NameSpace_Catalog",
69 (LPBYTE
)CatalogKeyName
,
72 /* Open the Catalog Key */
73 ErrorCode
= RegOpenKeyEx(ParentKey
,
79 /* If we didn't find the key, create it */
80 if (ErrorCode
== ERROR_SUCCESS
)
82 /* Fake that we opened an existing key */
83 CreateDisposition
= REG_OPENED_EXISTING_KEY
;
85 else if (ErrorCode
== ERROR_FILE_NOT_FOUND
)
87 /* Create the Catalog Name */
88 ErrorCode
= RegCreateKeyEx(ParentKey
,
92 REG_OPTION_NON_VOLATILE
,
99 HeapFree(WsSockHeap
, 0, CatalogKeyName
);
101 RegSize
= sizeof(DWORD
);
103 /* Fail if that didn't work */
104 if (ErrorCode
!= ERROR_SUCCESS
) return FALSE
;
106 /* Check if we had to create the key */
107 if (CreateDisposition
== REG_CREATED_NEW_KEY
)
109 /* Write the count of entries (0 now) */
110 ErrorCode
= RegSetValueEx(CatalogKey
,
111 "Num_Catalog_Entries",
116 if (ErrorCode
!= ERROR_SUCCESS
)
118 /* Close the key and fail */
119 RegCloseKey(CatalogKey
);
123 /* Write the first catalog entry Uniqe ID */
125 ErrorCode
= RegSetValueEx(CatalogKey
,
131 if (ErrorCode
!= ERROR_SUCCESS
)
133 /* Close the key and fail */
134 RegCloseKey(CatalogKey
);
138 /* Create a key for this entry */
139 ErrorCode
= RegCreateKeyEx(CatalogKey
,
143 REG_OPTION_NON_VOLATILE
,
148 if (ErrorCode
!= ERROR_SUCCESS
)
150 /* Close the key and fail */
151 RegCloseKey(CatalogKey
);
155 /* Close the key since we don't need it */
160 RegSize
= sizeof(UniqueId
);
161 /* Read the serial number */
162 ErrorCode
= RegQueryValueEx(CatalogKey
,
169 /* Check if it's missing for some reason */
170 if (ErrorCode
!= ERROR_SUCCESS
)
172 /* Write the first catalog entry Unique ID */
174 ErrorCode
= RegSetValueEx(CatalogKey
,
183 /* Set the Catalog Key */
184 Catalog
->CatalogKey
= CatalogKey
;
190 WsNcInitializeFromRegistry(IN PNSCATALOG Catalog
,
192 IN HANDLE CatalogEvent
)
194 INT ErrorCode
= WSASYSCALLFAILURE
;
196 /* Open the catalog */
197 if (WsNcOpen(Catalog
, ParentKey
))
200 ErrorCode
= WsNcRefreshFromRegistry(Catalog
, CatalogEvent
);
203 /* Return the status */
209 WsNcRefreshFromRegistry(IN PNSCATALOG Catalog
,
210 IN HANDLE CatalogEvent
)
213 BOOLEAN LocalEvent
= FALSE
;
214 LIST_ENTRY LocalList
;
217 DWORD CatalogEntries
;
218 PNSCATALOG_ENTRY CatalogEntry
;
221 DWORD RegType
= REG_DWORD
;
222 DWORD RegSize
= sizeof(DWORD
);
225 /* Check if we got an event */
228 /* Create an event ourselves */
229 CatalogEvent
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
230 if (!CatalogEvent
) return WSASYSCALLFAILURE
;
234 /* Lock the catalog */
237 /* Initialize our local list for the loop */
238 InitializeListHead(&LocalList
);
243 /* Setup notifications for the catalog entry */
244 ErrorCode
= WsSetupCatalogProtection(Catalog
->CatalogKey
,
247 if (ErrorCode
!= ERROR_SUCCESS
) break;
249 /* Check if we've changed till now */
250 if (UniqueId
== Catalog
->UniqueId
)
252 /* We haven't, so return */
253 ErrorCode
= ERROR_SUCCESS
;
257 /* Now Open the Entries */
258 ErrorCode
= RegOpenKeyEx(Catalog
->CatalogKey
,
263 if (ErrorCode
!= ERROR_SUCCESS
)
265 /* Critical failure */
266 ErrorCode
= WSASYSCALLFAILURE
;
270 /* Find out how many there are */
271 ErrorCode
= RegQueryValueEx(Catalog
->CatalogKey
,
272 "Num_Catalog_Entries",
275 (LPBYTE
)&CatalogEntries
,
277 if (ErrorCode
!= ERROR_SUCCESS
)
279 /* Critical failure */
280 ErrorCode
= WSASYSCALLFAILURE
;
284 /* Initialize them all */
285 for (i
= 1; i
<= CatalogEntries
; i
++)
287 /* Allocate a Catalog Entry Structure */
288 CatalogEntry
= WsNcEntryAllocate();
291 /* Not enough memory, fail */
292 ErrorCode
= WSA_NOT_ENOUGH_MEMORY
;
296 /* Initialize it from the Registry Key */
297 ErrorCode
= WsNcEntryInitializeFromRegistry(CatalogEntry
,
300 if (ErrorCode
!= ERROR_SUCCESS
)
302 /* We failed to get it, dereference the entry and leave */
303 WsNcEntryDereference(CatalogEntry
);
307 /* Insert it to our List */
308 InsertTailList(&LocalList
, &CatalogEntry
->CatalogLink
);
311 /* Close the catalog key */
312 RegCloseKey(EntriesKey
);
314 /* Check if we changed during our read and if we have success */
315 NewChangesMade
= WsCheckCatalogState(CatalogEvent
);
316 if (!NewChangesMade
&& ErrorCode
== ERROR_SUCCESS
)
318 /* All is good, update the protocol list */
319 WsNcUpdateNamespaceList(Catalog
, &LocalList
);
321 /* Update and return */
322 Catalog
->UniqueId
= UniqueId
;
326 /* We failed and/or catalog data changed, free what we did till now */
327 while (!IsListEmpty(&LocalList
))
329 /* Get the LP Catalog Item */
330 Entry
= RemoveHeadList(&LocalList
);
331 CatalogEntry
= CONTAINING_RECORD(Entry
, NSCATALOG_ENTRY
, CatalogLink
);
334 WsNcEntryDereference(CatalogEntry
);
336 } while (NewChangesMade
);
338 /* Release the lock */
341 /* Close the event, if any was created by us */
342 if (LocalEvent
) CloseHandle(CatalogEvent
);
350 WsNcEnumerateCatalogItems(IN PNSCATALOG Catalog
,
351 IN PNSCATALOG_ENUMERATE_PROC Callback
,
355 PNSCATALOG_ENTRY CatalogEntry
;
358 /* Lock the catalog */
361 /* Loop the entries */
362 Entry
= Catalog
->CatalogList
.Flink
;
363 while (GoOn
&& (Entry
!= &Catalog
->CatalogList
))
366 CatalogEntry
= CONTAINING_RECORD(Entry
, NSCATALOG_ENTRY
, CatalogLink
);
368 /* Move to the next one and call the callback */
369 Entry
= Entry
->Flink
;
370 GoOn
= Callback(Context
, CatalogEntry
);
373 /* Release the lock */
379 WsNcLoadProvider(IN PNSCATALOG Catalog
,
380 IN PNSCATALOG_ENTRY CatalogEntry
)
382 INT ErrorCode
= ERROR_SUCCESS
;
383 PNS_PROVIDER Provider
;
385 /* Lock the catalog */
388 /* Check if we have a provider already */
389 if (!CatalogEntry
->Provider
)
391 /* Allocate a provider */
392 if ((Provider
= WsNpAllocate()))
395 ErrorCode
= WsNpInitialize(Provider
,
396 CatalogEntry
->DllPath
,
397 &CatalogEntry
->ProviderId
);
400 if (ErrorCode
== ERROR_SUCCESS
)
402 /* Set the provider */
403 WsNcEntrySetProvider(CatalogEntry
, Provider
);
407 WsNpDereference(Provider
);
412 ErrorCode
= WSA_NOT_ENOUGH_MEMORY
;
416 /* Release the lock and return */
423 WsNcGetServiceClassInfo(IN PNSCATALOG Catalog
,
424 IN OUT LPDWORD BugSize
,
425 IN OUT LPWSASERVICECLASSINFOW lpServiceClassInfo
)
427 /* Not yet implemented in the spec? */
428 SetLastError(ERROR_SUCCESS
);
434 WsNcUpdateNamespaceList(IN PNSCATALOG Catalog
,
438 PNSCATALOG_ENTRY CatalogEntry
, OldCatalogEntry
;
441 /* First move from our list to the old one */
442 InsertHeadList(&Catalog
->CatalogList
, &TempList
);
443 RemoveEntryList(&Catalog
->CatalogList
);
444 InitializeListHead(&Catalog
->CatalogList
);
446 /* Loop every item on the list */
447 while (!IsListEmpty(List
))
449 /* Get the catalog entry */
450 Entry
= RemoveHeadList(List
);
451 CatalogEntry
= CONTAINING_RECORD(Entry
, NSCATALOG_ENTRY
, CatalogLink
);
453 /* Check if this item is already on our list */
454 Entry
= TempList
.Flink
;
455 while (Entry
!= &TempList
)
457 /* Get the catalog entry */
458 OldCatalogEntry
= CONTAINING_RECORD(Entry
, NSCATALOG_ENTRY
, CatalogLink
);
459 Entry
= Entry
->Flink
;
461 /* Check if they match */
462 if (IsEqualGUID(&CatalogEntry
->ProviderId
,
463 &OldCatalogEntry
->ProviderId
))
465 /* We have a match, use the old item instead */
466 WsNcEntryDereference(CatalogEntry
);
467 CatalogEntry
= OldCatalogEntry
;
468 RemoveEntryList(&CatalogEntry
->CatalogLink
);
470 /* Decrease the number of protocols we have */
471 Catalog
->ItemCount
--;
477 InsertTailList(&Catalog
->CatalogList
, &CatalogEntry
->CatalogLink
);
478 Catalog
->ItemCount
++;
481 /* If there's anything left on the temporary list */
482 while (!IsListEmpty(&TempList
))
485 Entry
= RemoveHeadList(&TempList
);
486 CatalogEntry
= CONTAINING_RECORD(Entry
, NSCATALOG_ENTRY
, CatalogLink
);
489 Catalog
->ItemCount
--;
490 WsNcEntryDereference(CatalogEntry
);
496 WsNcGetCatalogFromProviderId(IN PNSCATALOG Catalog
,
497 IN LPGUID ProviderId
,
498 OUT PNSCATALOG_ENTRY
*CatalogEntry
)
500 PLIST_ENTRY NextEntry
;
501 PNSCATALOG_ENTRY Entry
;
503 /* Lock the catalog */
506 /* Match the Id with all the entries in the List */
507 NextEntry
= Catalog
->CatalogList
.Flink
;
508 while (NextEntry
!= &Catalog
->CatalogList
)
510 /* Get the Current Entry */
511 Entry
= CONTAINING_RECORD(NextEntry
, NSCATALOG_ENTRY
, CatalogLink
);
512 NextEntry
= NextEntry
->Flink
;
514 /* Check if this is the Catalog Entry ID we want */
515 if (IsEqualGUID(&Entry
->ProviderId
, ProviderId
))
517 /* Check if it doesn't already have a provider */
518 if (!Entry
->Provider
)
520 /* Match, load the Provider */
521 WsNcLoadProvider(Catalog
, Entry
);
524 /* Reference the entry and return it */
525 InterlockedIncrement(&Entry
->RefCount
);
526 *CatalogEntry
= Entry
;
531 /* Release the catalog */
535 return ERROR_SUCCESS
;
540 WsNcMatchProtocols(IN DWORD NameSpace
,
541 IN LONG AddressFamily
,
542 IN LPWSAQUERYSETW QuerySet
)
544 DWORD ProtocolCount
= QuerySet
->dwNumberOfProtocols
;
545 LPAFPROTOCOLS AfpProtocols
= QuerySet
->lpafpProtocols
;
548 /* Check for valid family */
549 if (AddressFamily
!= -1)
551 /* Check if it's the magic */
552 if (AddressFamily
== AF_UNSPEC
) return TRUE
;
553 Family
= AddressFamily
;
557 /* No family given, check for namespace */
558 if (NameSpace
== NS_SAP
)
565 /* Other namespace, it's valid */
570 /* Now try to get a match */
571 while (ProtocolCount
--)
573 /* Check this protocol entry */
574 if ((AfpProtocols
->iAddressFamily
== AF_UNSPEC
) ||
575 (AfpProtocols
->iAddressFamily
== Family
))
581 /* Move to the next one */
591 WsNcRemoveCatalogItem(IN PNSCATALOG Catalog
,
592 IN PNSCATALOG_ENTRY Entry
)
594 /* Remove the entry from the list */
595 RemoveEntryList(&Entry
->CatalogLink
);
597 /* Decrease our count */
598 Catalog
->ItemCount
--;
603 WsNcDelete(IN PNSCATALOG Catalog
)
606 PNSCATALOG_ENTRY CatalogEntry
;
608 /* Check if we're initialized */
609 if (!Catalog
->CatalogList
.Flink
) return;
614 /* Loop every entry */
615 Entry
= Catalog
->CatalogList
.Flink
;
616 while (Entry
!= &Catalog
->CatalogList
)
619 CatalogEntry
= CONTAINING_RECORD(Entry
, NSCATALOG_ENTRY
, CatalogLink
);
621 /* Remove it and dereference it */
622 WsNcRemoveCatalogItem(Catalog
, CatalogEntry
);
623 WsNcEntryDereference(CatalogEntry
);
625 /* Move to the next entry */
626 Entry
= Catalog
->CatalogList
.Flink
;
629 /* Check if the catalog key is opened */
630 if (Catalog
->CatalogKey
)
633 RegCloseKey(Catalog
->CatalogKey
);
634 Catalog
->CatalogKey
= NULL
;
637 /* Release and delete the lock */
639 DeleteCriticalSection(&Catalog
->Lock
);
641 /* Delete the object */
642 HeapFree(WsSockHeap
, 0, Catalog
);