2d7d714c875cdef0d5da5984719440dc527011dd
[reactos.git] / dll / win32 / ws2_32_new / src / dcatalog.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS WinSock 2 API
4 * FILE: dcatalog.c
5 * PURPOSE: Transport Catalog Object
6 * PROGRAMMER: Alex Ionescu (alex@relsoft.net)
7 */
8
9 /* INCLUDES ******************************************************************/
10 #include "ws2_32.h"
11
12 /* DATA **********************************************************************/
13
14 #define TCCATALOG_NAME "Protocol_Catalog9"
15
16 #define WsTcLock() EnterCriticalSection((LPCRITICAL_SECTION)&Catalog->Lock);
17 #define WsTcUnlock() LeaveCriticalSection((LPCRITICAL_SECTION)&Catalog->Lock);
18
19 /* FUNCTIONS *****************************************************************/
20
21 PTCATALOG
22 WSAAPI
23 WsTcAllocate(VOID)
24 {
25 PTCATALOG Catalog;
26
27 /* Allocate the object */
28 Catalog = HeapAlloc(WsSockHeap, HEAP_ZERO_MEMORY, sizeof(*Catalog));
29
30 /* Return it */
31 return Catalog;
32 }
33
34 BOOL
35 WSAAPI
36 WsTcOpen(IN PTCATALOG Catalog,
37 IN HKEY ParentKey)
38 {
39 INT ErrorCode;
40 DWORD CreateDisposition;
41 HKEY CatalogKey, NewKey;
42 //DWORD CatalogEntries = 0;
43 DWORD RegType = REG_DWORD;
44 DWORD RegSize = sizeof(DWORD);
45 DWORD UniqueId = 0;
46 DWORD NewData = 0;
47
48 /* Initialize the catalog lock and namespace list */
49 InitializeCriticalSection((LPCRITICAL_SECTION)&Catalog->Lock);
50 InitializeListHead(&Catalog->ProtocolList);
51
52 /* Open the Catalog Key */
53 ErrorCode = RegOpenKeyEx(ParentKey,
54 TCCATALOG_NAME,
55 0,
56 MAXIMUM_ALLOWED,
57 &CatalogKey);
58
59 /* If we didn't find the key, create it */
60 if (ErrorCode == ERROR_SUCCESS)
61 {
62 /* Fake that we opened an existing key */
63 CreateDisposition = REG_OPENED_EXISTING_KEY;
64 }
65 else if (ErrorCode == ERROR_FILE_NOT_FOUND)
66 {
67 /* Create the Catalog Name */
68 ErrorCode = RegCreateKeyEx(ParentKey,
69 TCCATALOG_NAME,
70 0,
71 NULL,
72 REG_OPTION_NON_VOLATILE,
73 KEY_ALL_ACCESS,
74 NULL,
75 &CatalogKey,
76 &CreateDisposition);
77 }
78
79 /* Fail if that didn't work */
80 if (ErrorCode != ERROR_SUCCESS) return FALSE;
81
82 /* Check if we had to create the key */
83 if (CreateDisposition == REG_CREATED_NEW_KEY)
84 {
85 /* Write the count of entries (0 now) */
86 ErrorCode = RegSetValueEx(CatalogKey,
87 "Num_Catalog_Entries",
88 0,
89 REG_DWORD,
90 (LPBYTE)&NewData,
91 sizeof(NewData));
92 if (ErrorCode != ERROR_SUCCESS)
93 {
94 /* Close the key and fail */
95 RegCloseKey(CatalogKey);
96 return FALSE;
97 }
98
99 /* Write the first catalog entry ID */
100 NewData = 1001;
101 ErrorCode = RegSetValueEx(CatalogKey,
102 "Next_Catalog_Entry_ID",
103 0,
104 REG_DWORD,
105 (LPBYTE)&NewData,
106 sizeof(NewData));
107 if (ErrorCode != ERROR_SUCCESS)
108 {
109 /* Close the key and fail */
110 RegCloseKey(CatalogKey);
111 return FALSE;
112 }
113
114 /* Write the first catalog entry Uniqe ID */
115 NewData = 1;
116 ErrorCode = RegSetValueEx(CatalogKey,
117 "Serial_Access_Num",
118 0,
119 REG_DWORD,
120 (LPBYTE)&NewData,
121 sizeof(NewData));
122 if (ErrorCode != ERROR_SUCCESS)
123 {
124 /* Close the key and fail */
125 RegCloseKey(CatalogKey);
126 return FALSE;
127 }
128
129 /* Create a key for this entry */
130 ErrorCode = RegCreateKeyEx(CatalogKey,
131 "Catalog_Entries",
132 0,
133 NULL,
134 REG_OPTION_NON_VOLATILE,
135 KEY_ALL_ACCESS,
136 NULL,
137 &NewKey,
138 &CreateDisposition);
139 if (ErrorCode != ERROR_SUCCESS)
140 {
141 /* Close the key and fail */
142 RegCloseKey(CatalogKey);
143 return FALSE;
144 }
145
146 /* Close the key since we don't need it */
147 RegCloseKey(NewKey);
148 }
149 else
150 {
151 /* Read the serial number */
152 ErrorCode = RegQueryValueEx(CatalogKey,
153 "Serial_Access_Num",
154 0,
155 &RegType,
156 (LPBYTE)&UniqueId,
157 &RegSize);
158
159 /* Check if it's missing for some reason */
160 if (ErrorCode != ERROR_SUCCESS)
161 {
162 /* Write the first catalog entry Unique ID */
163 NewData = 1;
164 ErrorCode = RegSetValueEx(CatalogKey,
165 "Serial_Access_Num",
166 0,
167 REG_DWORD,
168 (LPBYTE)&NewData,
169 sizeof(NewData));
170 }
171 }
172
173 /* Set the Catalog Key */
174 Catalog->CatalogKey = CatalogKey;
175 return TRUE;
176 }
177
178 DWORD
179 WSAAPI
180 WsTcInitializeFromRegistry(IN PTCATALOG Catalog,
181 IN HKEY ParentKey,
182 IN HANDLE CatalogEvent)
183 {
184 INT ErrorCode = WSASYSCALLFAILURE;
185
186 /* Open the catalog */
187 if (WsTcOpen(Catalog, ParentKey))
188 {
189 /* Refresh it */
190 ErrorCode = WsTcRefreshFromRegistry(Catalog, CatalogEvent);
191 }
192
193 /* Return the status */
194 return ErrorCode;
195 }
196
197 DWORD
198 WSAAPI
199 WsTcRefreshFromRegistry(IN PTCATALOG Catalog,
200 IN HANDLE CatalogEvent)
201 {
202 INT ErrorCode;
203 BOOLEAN LocalEvent = FALSE;
204 LIST_ENTRY LocalList;
205 DWORD UniqueId;
206 HKEY EntriesKey;
207 DWORD CatalogEntries;
208 PTCATALOG_ENTRY CatalogEntry;
209 DWORD NextCatalogEntry;
210 BOOL NewChangesMade;
211 PLIST_ENTRY Entry;
212 DWORD RegType = REG_DWORD;
213 DWORD RegSize = sizeof(DWORD);
214 DWORD i;
215
216 /* Check if we got an event */
217 if (!CatalogEvent)
218 {
219 /* Create an event ourselves */
220 CatalogEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
221 if (!CatalogEvent) return WSASYSCALLFAILURE;
222 LocalEvent = TRUE;
223 }
224
225 /* Lock the catalog */
226 WsTcLock();
227
228 /* Initialize our local list for the loop */
229 InitializeListHead(&LocalList);
230
231 /* Start looping */
232 do
233 {
234 /* Setup notifications for the catalog entry */
235 ErrorCode = WsSetupCatalogProtection(Catalog->CatalogKey,
236 CatalogEvent,
237 &UniqueId);
238 if (ErrorCode != ERROR_SUCCESS) break;
239
240 /* Check if we've changed till now */
241 if (UniqueId == Catalog->UniqueId)
242 {
243 /* We haven't, so return */
244 ErrorCode = ERROR_SUCCESS;
245 break;
246 }
247
248 /* Now Open the Entries */
249 ErrorCode = RegOpenKeyEx(Catalog->CatalogKey,
250 "Catalog_Entries",
251 0,
252 MAXIMUM_ALLOWED,
253 &EntriesKey);
254 if (ErrorCode != ERROR_SUCCESS)
255 {
256 /* Critical failure */
257 ErrorCode = WSASYSCALLFAILURE;
258 break;
259 }
260
261 /* Get the next entry */
262 ErrorCode = RegQueryValueEx(Catalog->CatalogKey,
263 "Next_Catalog_Entry_ID",
264 0,
265 &RegType,
266 (LPBYTE)&NextCatalogEntry,
267 &RegSize);
268 if (ErrorCode != ERROR_SUCCESS)
269 {
270 /* Critical failure */
271 ErrorCode = WSASYSCALLFAILURE;
272 break;
273 }
274
275 /* Find out how many there are */
276 ErrorCode = RegQueryValueEx(Catalog->CatalogKey,
277 "Num_Catalog_Entries",
278 0,
279 &RegType,
280 (LPBYTE)&CatalogEntries,
281 &RegSize);
282 if (ErrorCode != ERROR_SUCCESS)
283 {
284 /* Critical failure */
285 ErrorCode = WSASYSCALLFAILURE;
286 break;
287 }
288
289 /* Initialize them all */
290 for (i = 1; i <= CatalogEntries; i++)
291 {
292 /* Allocate a Catalog Entry Structure */
293 CatalogEntry = WsTcEntryAllocate();
294 if (!CatalogEntry)
295 {
296 /* Not enough memory, fail */
297 ErrorCode = WSA_NOT_ENOUGH_MEMORY;
298 break;
299 }
300
301 /* Initialize it from the Registry Key */
302 ErrorCode = WsTcEntryInitializeFromRegistry(CatalogEntry,
303 EntriesKey,
304 i);
305 if (ErrorCode != ERROR_SUCCESS)
306 {
307 /* We failed to get it, dereference the entry and leave */
308 WsTcEntryDereference(CatalogEntry);
309 break;
310 }
311
312 /* Insert it to our List */
313 InsertTailList(&LocalList, &CatalogEntry->CatalogLink);
314 }
315
316 /* Close the catalog key */
317 RegCloseKey(EntriesKey);
318
319 /* Check if we changed during our read and if we have success */
320 NewChangesMade = WsCheckCatalogState(CatalogEvent);
321 if (!NewChangesMade && ErrorCode == ERROR_SUCCESS)
322 {
323 /* All is good, update the protocol list */
324 WsTcUpdateProtocolList(Catalog, &LocalList);
325
326 /* Update and return */
327 Catalog->UniqueId = UniqueId;
328 Catalog->NextId = NextCatalogEntry;
329 break;
330 }
331
332 /* We failed and/or catalog data changed, free what we did till now */
333 while (!IsListEmpty(&LocalList))
334 {
335 /* Get the LP Catalog Item */
336 Entry = RemoveHeadList(&LocalList);
337 CatalogEntry = CONTAINING_RECORD(Entry, TCATALOG_ENTRY, CatalogLink);
338
339 /* Dereference it */
340 WsTcEntryDereference(CatalogEntry);
341 }
342 } while (NewChangesMade);
343
344 /* Release the lock */
345 WsTcUnlock();
346
347 /* Close the event, if any was created by us */
348 if (LocalEvent) CloseHandle(CatalogEvent);
349
350 /* All Done */
351 return ErrorCode;
352 }
353
354 DWORD
355 WSAAPI
356 WsTcGetEntryFromAf(IN PTCATALOG Catalog,
357 IN INT AddressFamily,
358 IN PTCATALOG_ENTRY *CatalogEntry)
359 {
360 INT ErrorCode = WSAEINVAL;
361 PLIST_ENTRY NextEntry = Catalog->ProtocolList.Flink;
362 PTCATALOG_ENTRY Entry;
363
364 /* Assume failure */
365 *CatalogEntry = NULL;
366
367 /* Lock the catalog */
368 WsTcLock();
369
370 /* Match the Id with all the entries in the List */
371 while (NextEntry != &Catalog->ProtocolList)
372 {
373 /* Get the Current Entry */
374 Entry = CONTAINING_RECORD(NextEntry, TCATALOG_ENTRY, CatalogLink);
375 NextEntry = NextEntry->Flink;
376
377 /* Check if this is the Catalog Entry ID we want */
378 if (Entry->ProtocolInfo.iAddressFamily == AddressFamily)
379 {
380 /* Check if it doesn't already have a provider */
381 if (!Entry->Provider)
382 {
383 /* Match, load the Provider */
384 ErrorCode = WsTcLoadProvider(Catalog, Entry);
385
386 /* Make sure this didn't fail */
387 if (ErrorCode != ERROR_SUCCESS) break;
388 }
389
390 /* Reference the entry and return it */
391 InterlockedIncrement(&Entry->RefCount);
392 *CatalogEntry = Entry;
393 ErrorCode = ERROR_SUCCESS;
394 break;
395 }
396 }
397
398 /* Release the catalog */
399 WsTcUnlock();
400
401 /* Return */
402 return ErrorCode;
403 }
404
405 DWORD
406 WSAAPI
407 WsTcGetEntryFromCatalogEntryId(IN PTCATALOG Catalog,
408 IN DWORD CatalogEntryId,
409 IN PTCATALOG_ENTRY *CatalogEntry)
410 {
411 PLIST_ENTRY NextEntry = Catalog->ProtocolList.Flink;
412 PTCATALOG_ENTRY Entry;
413
414 /* Lock the catalog */
415 WsTcLock();
416
417 /* Match the Id with all the entries in the List */
418 while (NextEntry != &Catalog->ProtocolList)
419 {
420 /* Get the Current Entry */
421 Entry = CONTAINING_RECORD(NextEntry, TCATALOG_ENTRY, CatalogLink);
422 NextEntry = NextEntry->Flink;
423
424 /* Check if this is the Catalog Entry ID we want */
425 if (Entry->ProtocolInfo.dwCatalogEntryId == CatalogEntryId)
426 {
427 /* Check if it doesn't already have a provider */
428 if (!Entry->Provider)
429 {
430 /* Match, load the Provider */
431 WsTcLoadProvider(Catalog, Entry);
432 }
433
434 /* Reference the entry and return it */
435 InterlockedIncrement(&Entry->RefCount);
436 *CatalogEntry = Entry;
437 break;
438 }
439 }
440
441 /* Release the catalog */
442 WsTcUnlock();
443
444 /* Return */
445 return ERROR_SUCCESS;
446 }
447
448 DWORD
449 WSAAPI
450 WsTcGetEntryFromTriplet(IN PTCATALOG Catalog,
451 IN INT af,
452 IN INT type,
453 IN INT protocol,
454 IN DWORD StartId,
455 IN PTCATALOG_ENTRY *CatalogEntry)
456 {
457 INT ErrorCode = WSAEINVAL;
458 PLIST_ENTRY NextEntry = Catalog->ProtocolList.Flink;
459 PTCATALOG_ENTRY Entry;
460
461 /* Assume failure */
462 *CatalogEntry = NULL;
463
464 /* Lock the catalog */
465 WsTcLock();
466
467 /* Check if we are starting past 0 */
468 if (StartId)
469 {
470 /* Loop the list */
471 while (NextEntry != &Catalog->ProtocolList)
472 {
473 /* Get the Current Entry */
474 Entry = CONTAINING_RECORD(NextEntry, TCATALOG_ENTRY, CatalogLink);
475 NextEntry = NextEntry->Flink;
476
477 /* Check if this is the ID where we are starting */
478 if (Entry->ProtocolInfo.dwCatalogEntryId == StartId) break;
479 }
480 }
481
482 /* Match the Id with all the entries in the List */
483 while (NextEntry != &Catalog->ProtocolList)
484 {
485 /* Get the Current Entry */
486 Entry = CONTAINING_RECORD(NextEntry, TCATALOG_ENTRY, CatalogLink);
487 NextEntry = NextEntry->Flink;
488
489 /* Check if Address Family Matches or if it's wildcard */
490 if ((Entry->ProtocolInfo.iAddressFamily == af) || (af == AF_UNSPEC))
491 {
492 /* Check if Socket Type Matches or if it's wildcard */
493 if ((Entry->ProtocolInfo.iSocketType == type) || (type == 0))
494 {
495 /* Check if Protocol is In Range or if it's wildcard */
496 if (((Entry->ProtocolInfo.iProtocol >= protocol) &&
497 ((Entry->ProtocolInfo.iProtocol +
498 Entry->ProtocolInfo.iProtocolMaxOffset) <= protocol)) ||
499 (protocol == 0))
500 {
501 /* Check if it doesn't already have a provider */
502 if (!Entry->Provider)
503 {
504 /* Match, load the Provider */
505 ErrorCode = WsTcLoadProvider(Catalog, Entry);
506
507 /* Make sure this didn't fail */
508 if (ErrorCode != ERROR_SUCCESS) break;
509 }
510
511 /* Reference the entry and return it */
512 InterlockedIncrement(&Entry->RefCount);
513 *CatalogEntry = Entry;
514 ErrorCode = ERROR_SUCCESS;
515 break;
516 }
517 else
518 {
519 ErrorCode = WSAEPROTONOSUPPORT;
520 }
521 }
522 else
523 {
524 ErrorCode = WSAESOCKTNOSUPPORT;
525 }
526 }
527 else
528 {
529 ErrorCode = WSAEAFNOSUPPORT;
530 }
531 }
532
533 /* Release the catalog */
534 WsTcUnlock();
535
536 /* Return */
537 return ErrorCode;
538 }
539
540 PTPROVIDER
541 WSAAPI
542 WsTcFindProvider(IN PTCATALOG Catalog,
543 IN LPGUID ProviderId)
544 {
545 PTPROVIDER Provider;
546 PLIST_ENTRY Entry;
547 PTCATALOG_ENTRY CatalogEntry;
548
549 /* Loop the provider list */
550 Entry = Catalog->ProtocolList.Flink;
551 while (Entry != &Catalog->ProtocolList)
552 {
553 /* Get the entry */
554 CatalogEntry = CONTAINING_RECORD(Entry, TCATALOG_ENTRY, CatalogLink);
555
556 /* Move to the next one, get the provider */
557 Entry = Entry->Flink;
558 Provider = CatalogEntry->Provider;
559
560 /* Check for a match */
561 if ((Provider) &&
562 !(memcmp(&CatalogEntry->ProtocolInfo.ProviderId,
563 ProviderId,
564 sizeof(GUID))))
565 {
566 /* Found a match */
567 return Provider;
568 }
569 }
570
571 /* No match here */
572 return NULL;
573 }
574
575 DWORD
576 WSAAPI
577 WsTcLoadProvider(IN PTCATALOG Catalog,
578 IN PTCATALOG_ENTRY CatalogEntry)
579 {
580 INT ErrorCode = ERROR_SUCCESS;
581 PTPROVIDER Provider;
582
583 /* Lock the catalog */
584 WsTcLock();
585
586 /* Check if we have a provider already */
587 if (!CatalogEntry->Provider)
588 {
589 /* Try to find another instance */
590 Provider = WsTcFindProvider(Catalog,
591 &CatalogEntry->ProtocolInfo.ProviderId);
592
593 /* Check if we found one now */
594 if (Provider)
595 {
596 /* Set this one as the provider */
597 WsTcEntrySetProvider(CatalogEntry, Provider);
598 ErrorCode = ERROR_SUCCESS;
599 }
600 else
601 {
602 /* Nothing found, Allocate a provider */
603 if ((Provider = WsTpAllocate()))
604 {
605 /* Initialize it */
606 ErrorCode = WsTpInitialize(Provider,
607 CatalogEntry->DllPath,
608 &CatalogEntry->ProtocolInfo);
609
610 /* Ensure success */
611 if (ErrorCode == ERROR_SUCCESS)
612 {
613 /* Set the provider */
614 WsTcEntrySetProvider(CatalogEntry, Provider);
615 }
616
617 /* Dereference it */
618 WsTpDereference(Provider);
619 }
620 else
621 {
622 /* No memory */
623 ErrorCode = WSA_NOT_ENOUGH_MEMORY;
624 }
625 }
626 }
627
628 /* Release the lock */
629 WsTcUnlock();
630 return ErrorCode;
631 }
632
633 VOID
634 WSAAPI
635 WsTcUpdateProtocolList(IN PTCATALOG Catalog,
636 IN PLIST_ENTRY List)
637 {
638 LIST_ENTRY TempList;
639 PTCATALOG_ENTRY CatalogEntry, OldCatalogEntry;
640 PLIST_ENTRY Entry;
641
642 /* First move from our list to the old one */
643 InsertHeadList(&Catalog->ProtocolList, &TempList);
644 RemoveEntryList(&Catalog->ProtocolList);
645 InitializeListHead(&Catalog->ProtocolList);
646
647 /* Loop every item on the list */
648 while (!IsListEmpty(List))
649 {
650 /* Get the catalog entry */
651 Entry = RemoveHeadList(List);
652 CatalogEntry = CONTAINING_RECORD(Entry, TCATALOG_ENTRY, CatalogLink);
653
654 /* Check if this item is already on our list */
655 Entry = TempList.Flink;
656 while (Entry != &TempList)
657 {
658 /* Get the catalog entry */
659 OldCatalogEntry = CONTAINING_RECORD(Entry, TCATALOG_ENTRY, CatalogLink);
660 Entry = Entry->Flink;
661
662 /* Check if they match */
663 if (CatalogEntry->ProtocolInfo.dwCatalogEntryId ==
664 OldCatalogEntry->ProtocolInfo.dwCatalogEntryId)
665 {
666 /* We have a match, use the old item instead */
667 WsTcEntryDereference(CatalogEntry);
668 CatalogEntry = OldCatalogEntry;
669 RemoveEntryList(&CatalogEntry->CatalogLink);
670
671 /* Decrease the number of protocols we have */
672 Catalog->ItemCount--;
673 break;
674 }
675 }
676
677 /* Add this item */
678 InsertTailList(&Catalog->ProtocolList, &CatalogEntry->CatalogLink);
679 Catalog->ItemCount++;
680 }
681
682 /* If there's anything left on the temporary list */
683 while (!IsListEmpty(&TempList))
684 {
685 /* Get the entry */
686 Entry = RemoveHeadList(&TempList);
687 CatalogEntry = CONTAINING_RECORD(Entry, TCATALOG_ENTRY, CatalogLink);
688
689 /* Remove it */
690 Catalog->ItemCount--;
691 WsTcEntryDereference(CatalogEntry);
692 }
693 }
694
695 VOID
696 WSAAPI
697 WsTcEnumerateCatalogItems(IN PTCATALOG Catalog,
698 IN PTCATALOG_ENUMERATE_PROC Callback,
699 IN PVOID Context)
700 {
701 PLIST_ENTRY Entry;
702 PTCATALOG_ENTRY CatalogEntry;
703 BOOL GoOn = TRUE;
704
705 /* Lock the catalog */
706 WsTcLock();
707
708 /* Loop the entries */
709 Entry = Catalog->ProtocolList.Flink;
710 while (GoOn && (Entry != &Catalog->ProtocolList))
711 {
712 /* Get the entry */
713 CatalogEntry = CONTAINING_RECORD(Entry, TCATALOG_ENTRY, CatalogLink);
714
715 /* Move to the next one and call the callback */
716 Entry = Entry->Flink;
717 GoOn = Callback(Context, CatalogEntry);
718 }
719
720 /* Release lock */
721 WsTcUnlock();
722 }
723
724 DWORD
725 WSAAPI
726 WsTcFindIfsProviderForSocket(IN PTCATALOG Catalog,
727 IN SOCKET Handle)
728 {
729 PTPROVIDER Provider;
730 IN SOCKET NewHandle;
731 INT Error;
732 DWORD OptionLength;
733 PLIST_ENTRY Entry;
734 WSAPROTOCOL_INFOW ProtocolInfo;
735 DWORD UniqueId;
736 INT ErrorCode;
737 PTCATALOG_ENTRY CatalogEntry;
738
739 /* Get the catalog lock */
740 WsTcLock();
741
742 /* Loop as long as the catalog changes */
743 CatalogChanged:
744
745 /* Loop every provider */
746 Entry = Catalog->ProtocolList.Flink;
747 while (Entry != &Catalog->ProtocolList)
748 {
749 /* Get the catalog entry */
750 CatalogEntry = CONTAINING_RECORD(Entry, TCATALOG_ENTRY, CatalogLink);
751
752 /* Move to the next entry */
753 Entry = Entry->Flink;
754
755 /* Skip it if it doesn't support IFS */
756 if (!(CatalogEntry->ProtocolInfo.dwServiceFlags1 & XP1_IFS_HANDLES)) continue;
757
758 /* Check if we need to load it */
759 if (!(Provider = CatalogEntry->Provider))
760 {
761 /* Load it */
762 ErrorCode = WsTcLoadProvider(Catalog, CatalogEntry);
763
764 /* Skip it if we failed to load it */
765 if (ErrorCode != ERROR_SUCCESS) continue;
766
767 /* Get the provider again */
768 Provider = CatalogEntry->Provider;
769 }
770
771 /* Reference the entry and get our unique id */
772 InterlockedIncrement(&CatalogEntry->RefCount);
773 UniqueId = Catalog->UniqueId;
774
775 /* Release the lock now */
776 WsTcUnlock();
777
778 /* Get the catalog entry ID */
779 OptionLength = sizeof(ProtocolInfo);
780 ErrorCode = Provider->Service.lpWSPGetSockOpt(Handle,
781 SOL_SOCKET,
782 SO_PROTOCOL_INFOW,
783 (PCHAR)&ProtocolInfo,
784 (LPINT)&OptionLength,
785 &Error);
786
787 /* Dereference the entry and check the result */
788 WsTcEntryDereference(CatalogEntry);
789 if (ErrorCode != ERROR_SUCCESS)
790 {
791 /* Lock and make sure this provider is still valid */
792 WsTcLock();
793 if (UniqueId == Catalog->UniqueId) continue;
794
795 /* It changed! We need to start over */
796 goto CatalogChanged;
797 }
798
799 /* Now get the IFS handle */
800 NewHandle = WPUModifyIFSHandle(ProtocolInfo.dwCatalogEntryId,
801 Handle,
802 &Error);
803
804 /* Check if the socket is invalid */
805 if (NewHandle == INVALID_SOCKET) return WSAENOTSOCK;
806
807 /* We suceeded, get out of here */
808 return ERROR_SUCCESS;
809 }
810
811 /* Unrecognized socket if we get here: note, we still have the lock */
812 WsTcUnlock();
813 return WSAENOTSOCK;
814 }
815
816 VOID
817 WSAAPI
818 WsTcRemoveCatalogItem(IN PTCATALOG Catalog,
819 IN PTCATALOG_ENTRY Entry)
820 {
821 /* Remove the entry from the list */
822 RemoveEntryList(&Entry->CatalogLink);
823
824 /* Decrease our count */
825 Catalog->ItemCount--;
826 }
827
828 VOID
829 WSAAPI
830 WsTcDelete(IN PTCATALOG Catalog)
831 {
832 PLIST_ENTRY Entry;
833 PTCATALOG_ENTRY CatalogEntry;
834
835 /* Check if we're initialized */
836 if (!Catalog->ProtocolList.Flink) return;
837
838 /* Acquire lock */
839 WsTcLock();
840
841 /* Loop every entry */
842 Entry = Catalog->ProtocolList.Flink;
843 while (Entry != &Catalog->ProtocolList)
844 {
845 /* Get this entry */
846 CatalogEntry = CONTAINING_RECORD(Entry, TCATALOG_ENTRY, CatalogLink);
847
848 /* Remove it */
849 WsTcRemoveCatalogItem(Catalog, CatalogEntry);
850
851 /* Dereference it */
852 WsTcEntryDereference(CatalogEntry);
853
854 /* Move to the next entry */
855 Entry = Catalog->ProtocolList.Flink;
856 }
857
858 /* Check if the catalog key is opened */
859 if (Catalog->CatalogKey)
860 {
861 /* Close it */
862 RegCloseKey(Catalog->CatalogKey);
863 Catalog->CatalogKey = NULL;
864 }
865
866 /* Release and delete the lock */
867 WsTcUnlock();
868 DeleteCriticalSection((LPCRITICAL_SECTION)&Catalog->Lock);
869
870 /* Delete the object */
871 HeapFree(WsSockHeap, 0, Catalog);
872 }